<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK: поиск картинки одновременно с движением мышки]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=15684</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=15684&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK: поиск картинки одновременно с движением мышки».]]></description>
		<lastBuildDate>Mon, 12 Oct 2020 11:23:06 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142618#p142618</link>
			<description><![CDATA[<p>Если честно, то не очень хочется.<br />Надо проводить тесты, делать выводы... Лень.</p>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Mon, 12 Oct 2020 11:23:06 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142618#p142618</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142617#p142617</link>
			<description><![CDATA[<div class="quotebox"><cite>Malcev пишет:</cite><blockquote><p>Что там еще описывать?</p></blockquote></div><p>Имею в виду что-то в <a href="https://ichip.ru/obzory/programmy-i-prilozheniya/testiruem-brauzery-sravnenie-chrome-firefox-edge-co-718142">таком</a> стиле.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Mon, 12 Oct 2020 10:35:03 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142617#p142617</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142609#p142609</link>
			<description><![CDATA[<div class="quotebox"><cite>teadrinker пишет:</cite><blockquote><p>Вот это было бы интересно отдельным постом, со сравнительным анализом</p></blockquote></div><p>Так я на форуме постил различные варианты.<br />Что там еще описывать?<br /></p><div class="quotebox"><blockquote><p>Чисто гипотетически, можно ли на разных компьютерах искать одно и то же искомое изображение?</p></blockquote></div><p>Изучайте OpenCV.</p>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Mon, 12 Oct 2020 00:53:44 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142609#p142609</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142608#p142608</link>
			<description><![CDATA[<p>Чисто гипотетически, можно ли на разных компьютерах искать одно и то же искомое изображение? Может есть общий знаменатель в этом деле?<br />Ведь у разных мониторов свои настройки, а значит отображаемая картинка на экране будет отличаться и поиск может показывать отрицательный результат.</p><p>картинка = Х.png<br />на компьютере 1, будет совпадение<br />на компьютере 2, при таких же обстоятельствах, может отсутствовать совпадение</p>]]></description>
			<author><![CDATA[null@example.com (Botsy)]]></author>
			<pubDate>Sun, 11 Oct 2020 23:36:09 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142608#p142608</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142607#p142607</link>
			<description><![CDATA[<div class="quotebox"><cite>Malcev пишет:</cite><blockquote><p>Большую работу я проделал, когда начал изучать способы получения экрана</p></blockquote></div><p>Вот это было бы интересно отдельным постом, со сравнительным анализом. <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /></p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sun, 11 Oct 2020 22:55:48 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142607#p142607</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142606#p142606</link>
			<description><![CDATA[<p><strong>Malcev</strong> не знал что есть разница в версиях AHK. Запустил с х32, все норм скрипт не выкидывает и работает. Буду разбираться.</p>]]></description>
			<author><![CDATA[null@example.com (Botsy)]]></author>
			<pubDate>Sun, 11 Oct 2020 22:26:40 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142606#p142606</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142600#p142600</link>
			<description><![CDATA[<p>Большую работу я проделал, когда начал изучать способы получения экрана.<br />А сейчас я просто объединил получение экрана через desktop duplication с функцией поиска, которую написал <strong>Rseding91</strong>.<br />Я создал отдельную тему по скрипту.<br /><a href="http://forum.script-coding.com/viewtopic.php?pid=142599">http://forum.script-coding.com/viewtopic.php?pid=142599</a><br />Виндовс без разницы какой, главное чтобы win8+.<br />Ahk должен быть 32 бит.<br />Gdip здесь не нужна.</p>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Sun, 11 Oct 2020 19:31:25 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142600#p142600</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142593#p142593</link>
			<description><![CDATA[<p><strong>Malcev</strong> Похоже вы проделали большую работу, спасибо за интерес!<br />Конечно для меня написанный код сложный, пробовал разобраться, но пока рано. Библиотеки Gdip у меня были, подключил их пробовал запустить ваш код, но у меня скрипт просто закрывается. </p><div class="quotebox"><blockquote><p>Работает только на 32 битах.</p></blockquote></div><p> у меня винда х64, наверное из-за этого. Пока под рукой нет х32, проверю позже на другом ПК.</p>]]></description>
			<author><![CDATA[null@example.com (Botsy)]]></author>
			<pubDate>Sun, 11 Oct 2020 12:15:40 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142593#p142593</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142590#p142590</link>
			<description><![CDATA[<p>Убрал ненужные функции из gdip и заменил default variation на 1, так как при нуле иногда не срабатывает.<br />Работает только на 32 битах.<br /></p><div class="codebox"><pre><code>needle := &quot;needle.bmp&quot;
x1 := 0, y1 := 0, x2 := 1920, y2 := 1080


setbatchlines -1
OnExit(&quot;ExitFunc&quot;)
IDXGIFactory := CreateDXGIFactory()
if !IDXGIFactory
{
   MsgBox, 16, Error, Create IDXGIFactory failed.
   ExitApp
}
loop
{
   IDXGIFactory_EnumAdapters(IDXGIFactory, A_Index-1, IDXGIAdapter)
   loop
   {
      hr := IDXGIAdapter_EnumOutputs(IDXGIAdapter, A_Index-1, IDXGIOutput)
      if (hr = &quot;DXGI_ERROR_NOT_FOUND&quot;)
         break
      VarSetCapacity(DXGI_OUTPUT_DESC, 88+A_PtrSize, 0)
      IDXGIOutput_GetDesc(IDXGIOutput, &amp;DXGI_OUTPUT_DESC)
      hWidth := NumGet(DXGI_OUTPUT_DESC, 72, &quot;int&quot;)
      hHeight := NumGet(DXGI_OUTPUT_DESC, 76, &quot;int&quot;)
      AttachedToDesktop := NumGet(DXGI_OUTPUT_DESC, 80, &quot;int&quot;)
      if (AttachedToDesktop = 1)
         break 2         
   }
}
if (AttachedToDesktop != 1)
{
   MsgBox, 16, Error, No adapter attached to desktop
   ExitApp
}
D3D11CreateDevice(IDXGIAdapter, D3D_DRIVER_TYPE_UNKNOWN := 0, 0, 0, 0, 0, D3D11_SDK_VERSION := 7, d3d_device, 0, d3d_context)
IDXGIOutput1 := IDXGIOutput1_Query(IDXGIOutput)
IDXGIOutput1_DuplicateOutput(IDXGIOutput1, d3d_device, Duplication)
VarSetCapacity(DXGI_OUTDUPL_DESC, 36, 0)
IDXGIOutputDuplication_GetDesc(Duplication, &amp;DXGI_OUTDUPL_DESC)
DesktopImageInSystemMemory := NumGet(DXGI_OUTDUPL_DESC, 32, &quot;uint&quot;)
sleep 50   ; As I understand - need some sleep for successful connecting to IDXGIOutputDuplication interface
VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
NumPut(hWidth, D3D11_TEXTURE2D_DESC, 0, &quot;uint&quot;)   ; Width
NumPut(hHeight, D3D11_TEXTURE2D_DESC, 4, &quot;uint&quot;)   ; Height
NumPut(1, D3D11_TEXTURE2D_DESC, 8, &quot;uint&quot;)   ; MipLevels
NumPut(1, D3D11_TEXTURE2D_DESC, 12, &quot;uint&quot;)   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, &quot;uint&quot;)   ; Format 
NumPut(1, D3D11_TEXTURE2D_DESC, 20, &quot;uint&quot;)   ; SampleDescCount
NumPut(0, D3D11_TEXTURE2D_DESC, 24, &quot;uint&quot;)   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, &quot;uint&quot;)   ; Usage
NumPut(0, D3D11_TEXTURE2D_DESC, 32, &quot;uint&quot;)   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, D3D11_TEXTURE2D_DESC, 36, &quot;uint&quot;)   ; CPUAccessFlags
NumPut(0, D3D11_TEXTURE2D_DESC, 40, &quot;uint&quot;)   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &amp;D3D11_TEXTURE2D_DESC, 0, staging_tex)

DllCall(&quot;LoadLibrary&quot;, &quot;str&quot;, &quot;gdiplus&quot;)
VarSetCapacity(si, 8+2*A_PtrSize, 0)
NumPut(0x1, si, &quot;uint&quot;)
DllCall(&quot;gdiplus\GdiplusStartup&quot;, &quot;ptr*&quot;, pToken, &quot;ptr&quot;, &amp;si, &quot;ptr&quot;, 0)
DllCall(&quot;gdiplus\GdipCreateBitmapFromFile&quot;, &quot;ptr&quot;, &amp;needle, &quot;ptr*&quot;, pBitmapNeedle)
DllCall(&quot;gdiplus\GdipGetImageWidth&quot;, &quot;ptr&quot;, pBitmapNeedle, &quot;uint*&quot;, nWidth)
DllCall(&quot;gdiplus\GdipGetImageHeight&quot;, &quot;ptr&quot;, pBitmapNeedle, &quot;uint*&quot;, nHeight)
VarSetCapacity(Rect, 16, 0)
NumPut(nWidth, Rect, 8, &quot;uint&quot;)
NumPut(nHeight, Rect, 12, &quot;uint&quot;)
VarSetCapacity(nBitmapData, 16+2*A_PtrSize, 0)
DllCall(&quot;Gdiplus\GdipBitmapLockBits&quot;, &quot;ptr&quot;, pBitmapNeedle, &quot;ptr&quot;, &amp;Rect, &quot;uint&quot;, ReadWrite := 3, &quot;int&quot;, Format32bppArgb := 2498570, &quot;ptr&quot;, &amp;nBitmapData)
nStride := NumGet(nBitmapData, 8, &quot;int&quot;)
nScan := NumGet(nBitmapData, 16, &quot;ptr&quot;)
x2 -= nWidth-1
y2 -= nHeight-1
return

f11::
loop 1
{
   tooltip % A_Index
   loop
   {
      VarSetCapacity(DXGI_OUTDUPL_FRAME_INFO, 48, 0)
      AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, INFINITE := 0xFFFFFFFF, &amp;DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
      LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, &quot;int64&quot;)
      if (LastPresentTime != 0)
      {
         if (DesktopImageInSystemMemory = 1)
         {
            VarSetCapacity(DXGI_MAPPED_RECT, A_PtrSize*2, 0)
            IDXGIOutputDuplication_MapDesktopSurface(Duplication, &amp;DXGI_MAPPED_RECT)
            hStride := NumGet(DXGI_MAPPED_RECT, 0, &quot;int&quot;)
            hScan := NumGet(DXGI_MAPPED_RECT, A_PtrSize, &quot;ptr&quot;)
         }
         else
         {
            tex := ID3D11Texture2D_Query(desktop_resource)
            ID3D11DeviceContext_CopyResource(d3d_context, staging_tex, tex)
            VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
            ID3D11DeviceContext_Map(d3d_context, staging_tex, 0, D3D11_MAP_READ := 1, 0, &amp;D3D11_MAPPED_SUBRESOURCE)
            hScan := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, &quot;ptr&quot;)
            hStride := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, &quot;uint&quot;)
         }

         if !Gdip_FastImageSearch(hStride, hScan, hWidth, hHeight, nStride, nScan, nWidth, nHeight, x, y, x1, y1, x2, y2)
            msgbox % x &quot; - &quot; y

         if (DesktopImageInSystemMemory = 1)
            IDXGIOutputDuplication_UnMapDesktopSurface(Duplication)
         else
         {
            ID3D11DeviceContext_Unmap(d3d_context, staging_tex, 0)
            ObjRelease(tex)
         }
         ObjRelease(desktop_resource)
         IDXGIOutputDuplication_ReleaseFrame(duplication)
         break
      }
      ObjRelease(desktop_resource)
      IDXGIOutputDuplication_ReleaseFrame(duplication)
   }
}
return

ExitFunc()
{
   DllCall(&quot;Gdiplus\GdipBitmapUnlockBits&quot;, &quot;ptr&quot;, pBitmapNeedle, &quot;ptr&quot;, &amp;nBitmapData)
   DllCall(&quot;gdiplus\GdipDisposeImage&quot;, &quot;ptr&quot;, pBitmapNeedle)
   ObjRelease(staging_tex)
   ObjRelease(d3d_device)
   ObjRelease(d3d_context)
   ObjRelease(duplication)
   ObjRelease(IDXGIAdapter)
   ObjRelease(IDXGIOutput)
   ObjRelease(IDXGIOutput1)
   ObjRelease(IDXGIFactory)
}



CreateDXGIFactory()
{
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;DXGI&quot;)
      DllCall(&quot;LoadLibrary&quot;,&quot;str&quot;,&quot;DXGI&quot;)
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;D3D11&quot;)
      DllCall(&quot;LoadLibrary&quot;,&quot;str&quot;,&quot;D3D11&quot;)
   GUID(riid, &quot;{7b7166ec-21c7-44ae-b21a-c9ae321ae369}&quot;)
   hr := DllCall(&quot;DXGI\CreateDXGIFactory1&quot;, &quot;ptr&quot;, &amp;riid, &quot;ptr*&quot;, ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return ppFactory
}

IDXGIFactory_EnumAdapters(this, Adapter, ByRef ppAdapter)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), &quot;ptr&quot;, this, &quot;uint&quot;, Adapter, &quot;ptr*&quot;, ppAdapter)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

IDXGIAdapter_EnumOutputs(this, Output, ByRef ppOutput)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), &quot;ptr&quot;, this, &quot;uint&quot;, Output, &quot;ptr*&quot;, ppOutput)
   if hr or ErrorLevel
   {
      if (hr&amp;=0xFFFFFFFF) = 0x887A0002   ; DXGI_ERROR_NOT_FOUND
         return &quot;DXGI_ERROR_NOT_FOUND&quot;
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   }
}

IDXGIAdapter_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*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)
}

IDXGIOutput_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*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)
}

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

IDXGIOutputDuplication_AcquireNextFrame(this, TimeoutInMilliseconds, pFrameInfo, ByRef ppDesktopResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), &quot;ptr&quot;, this, &quot;uint&quot;, TimeoutInMilliseconds, &quot;ptr&quot;, pFrameInfo, &quot;ptr*&quot;, ppDesktopResource)
   if hr or ErrorLevel
   {
      if (hr&amp;=0xFFFFFFFF) = 0x887A0027   ; DXGI_ERROR_WAIT_TIMEOUT
         return &quot;DXGI_ERROR_WAIT_TIMEOUT&quot;
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   }
}

D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ByRef ppDevice, ByRef pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall(&quot;D3D11\D3D11CreateDevice&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;, ppDevice, &quot;ptr*&quot;, pFeatureLevel, &quot;ptr*&quot;, ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

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

IDXGIOutputDuplication_MapDesktopSurface(this, pLockedRect)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pLockedRect)
   if hr or ErrorLevel
   {
      if (hr&amp;=0xFFFFFFFF) = 0x887A0004   ; DXGI_ERROR_UNSUPPORTED
         return &quot;DXGI_ERROR_UNSUPPORTED&quot;
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   }
}

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

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

IDXGIOutput1_DuplicateOutput(this, pDevice, ByRef ppOutputDuplication)
{
   hr := DllCall(NumGet(NumGet(this+0)+22*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDevice, &quot;ptr*&quot;, ppOutputDuplication)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

IDXGIOutput1_Query(IDXGIOutput)
{ 
   hr := ComObjQuery(IDXGIOutput, &quot;{00cddea8-939b-4b83-a340-a685226666cc}&quot;)
   if !hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return hr
}

ID3D11Texture2D_Query(desktop_resource)
{ 
   hr := ComObjQuery(desktop_resource, &quot;{6f15aaf2-d208-4e89-9ab4-489535d34f9c}&quot;)
   if !hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return hr
}

ID3D11DeviceContext_CopyResource(this, pDstResource, pSrcResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+47*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDstResource, &quot;ptr&quot;, pSrcResource)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11DeviceContext_CopySubresourceRegion(this, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox)
{
   hr := DllCall(NumGet(NumGet(this+0)+46*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDstResource, &quot;uint&quot;, DstSubresource, &quot;uint&quot;, DstX, &quot;uint&quot;, DstY, &quot;uint&quot;, DstZ, &quot;ptr&quot;, pSrcResource, &quot;uint&quot;, SrcSubresource, &quot;ptr&quot;, pSrcBox)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11DeviceContext_Map(this, pResource, Subresource, MapType, MapFlags, pMappedResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pResource, &quot;uint&quot;, Subresource, &quot;uint&quot;, MapType, &quot;uint&quot;, MapFlags, &quot;ptr&quot;, pMappedResource)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11DeviceContext_Unmap(this, pResource, Subresource)
{
   hr := DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pResource, &quot;uint&quot;, Subresource)
   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
}



;**********************************************************************************
;
; Gdip_FastImageSearch() - 08/MARCH/2013 21:00h BRT
; by MasterFocus, based on previous work by tic and Rseding91
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition exclusively for these users:
; - tic , Rseding91 , guest3456
;
;**********************************************************************************

;==================================================================================
;
; pBitmapHayStack
;   Use &quot;Screen&quot; or an already existing pBitmap
;   Default: &quot;&quot; (returns -1)
;
; pBitmapNeedle
;   A filename or an already existing pBitmap
;  Default: &quot;&quot; (returns -1)
;
; x and y
;   Variables to store the X and Y coordinates of the image if it&#039;s found
;   Default: &quot;&quot; for both
;
; sx1, sy1, sx2 and sy2
;   These can be used to crop the search area within the haystack
;   Default: &quot;&quot; for all (does not crop)
;
; Variation and Trans
;   Same as the builtin ImageSearch command (I guess we all know that)
;   Default: 0 for both
;
; w and h
;   Parameters used to resize the needle (-1 for one of those will mantain aspect ratio)
;   Default: 0 for both
;
; sd
;   Search direction:
;   0 = auto detect best direction [default]
;   1 = left-&gt;right, top-&gt;bottom ;; 2 = left-&gt;right, bottom-&gt;top
;   3 = right-&gt;left, bottom-&gt;top ;; 4 = right-&gt;left, top-&gt;bottom
;
; UseLastData
;   Tells the function to keep same haystack and/or needle data for future use
;   - If this is set and there is no previous data, the current data is used and saved
;   - If this is not set, any saved data is deleted/released/unlocked
;   0 or 0x00 = not set for the haystack and not set for the needle
;   1 or 0x01 = set for the haystack and not set for the needle
;   2 or 0x10 = not set for the haystack and set for the needle
;   3 or 0x11 = set for the haystack and set for the needle
;   (specially useful for multiple searches with the same haystack and/or needle)
;   Default: 0
;
; nWidth and nHeight
;   These can be used to store, out of the function, the width and height of the needle internally used
;   (retrieved from the resized needle, if w or h is set)
;   (specially useful for multiple searches with the same haystack and/or needle)
;==================================================================================

Gdip_FastImageSearch(hStride, hScan, hWidth, hHeight, nStride, nScan, nWidth, nHeight, ByRef x=&quot;&quot;, ByRef y=&quot;&quot;, x1=&quot;&quot;, y1=&quot;&quot;, x2=&quot;&quot;, y2=&quot;&quot;, Variation=1, Trans=0, sd=1)
{
    static _ImageSearch1, _ImageSearch2, _PixelAverage, Ptr, PtrA
    if !_ImageSearch1
    {
        Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
        , PtrA := A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;
        
        MCode_ImageSearch1 := &quot;8B4C243483EC10803900538B5C2434555657750C80790100750680790200744B8B54243885D27E478B7C2430478BEA908B7424&quot;
        . &quot;3485F67E2C8BC78D9B000000008A50013A510275128A103A5101750B8A50FF3A117504C640020083C0044E75E08B54243803FB4D75C7EB048B5424388B&quot;
        . &quot;4424488944241C3B4424500F8D800200008B4C243C8BF90FAFF88D4402FF0FAFC1897C2418894424148DA424000000008B742444897424543B74244C0F&quot;
        . &quot;8D300200008B74245C83FE0175648B6C243033D2453B5424380F8D5402000033F6397424347E428B4C24548B5C242C8D0C8F8BC58D4C19018A58013A59&quot;
        . &quot;01750E8A183A1975088A58FF3A59FF740A807802000F85B60100004683C10483C0043B7424347CD38B5C2440037C243C4203EBEBA383FE020F85860000&quot;
        . &quot;008BF88BC14A8BCBF7D8F7D98BF20FAFF38B5C243089442410894C24488D6C1E01EB068D9B0000000083FAFF0F8EC701000033F6397424347E468B4C24&quot;
        . &quot;548B5C242C8D0C8F8BC58D4C19018A58013A5901750E8A183A1975088A58FF3A59FF740A807802000F85290100004683C10483C0043B7424347CD38B44&quot;
        . &quot;24108B4C244803F84A03E9EBA283FE030F85840000004A8BFAF7D90FAFFB8BF3F7DE8BE8894C2410897424488D490083FAFF0F8E470100008B44243448&quot;
        . &quot;83F8FF7E518B7424308B5C242C8D0C878D4C31018B74245403F08D74B5008D741E018A59013A5E01750E8A193A1E75088A59FF3A5EFF740A807902000F&quot;
        . &quot;859B0000004883EE0483E90483F8FF7FD48B7424488B4C241003E94A03FEEB9583FE040F85DC00000033ED896C24488D9B00000000395424480F8DC600&quot;
        . &quot;00008B4424344883F8FF7E4D8B4C24308B74242C8D5485008D4C0A018B54245403D08D14978D7432018A51013A5601750E8A113A1675088A51FF3A56FF&quot;
        . &quot;74068079020075224883EE0483E90483F8FF7FD88B5424388B4C243CFF44244803F903EBEB958B5C24408B4424548B7C24188B5424388B4C243C403B44&quot;
        . &quot;244C894424548B4424140F8CD0FDFFFF8B74241C4603C103F98974241C89442414897C24183B7424500F8C9FFDFFFF8B4C24248B5424285F5E5DC701FF&quot;
        . &quot;FFFFFFC702FFFFFFFF83C8FF5B83C410C38B4424248B4C24548B5424285F89088B4424185E5D890233C05B83C410C3&quot;
        
        MCode_ImageSearch2 := &quot;8B4C24348B54241883EC2C803900538B5C2450555657750C80790100750680790200744E8B6C244C85D27E4A8D7D0189542470&quot;
        . &quot;8B74245085F67E298BC78D49008A50013A510275128A103A5101750B8A50FF3A117504C640020083C0044E75E08B6C244C03FBFF4C247075C78B542454&quot;
        . &quot;EB048B6C244C8B442464894424183B44246C0F8D0C0400008B7C24588B74247C8BCF0FAFC8894C24148B8C248000000003C88D4402FF0FAFCF0FAFC789&quot;
        . &quot;4424108B442474894C2430EB068D9B000000008B4C2460894C24643B4C24680F8DA40300008BD30FAF94248000000003D58D0CB20FB611894C24348B4C&quot;
        . &quot;246003CE8B7424308D0C8E034C244889542438894C242CEB048B4C242C0FB6098D34013BD67F062BC83BD17D0E8B4C2434807903000F85350300008B4C&quot;
        . &quot;247883F9010F85AD0000008B742414C7442470000000008D4D018B542470894C2424897424283B5424540F8D5C03000033ED396C24507E698B5424648D&quot;
        . &quot;14968B7424488D7432018BFF0FB656010FB679018D1C023BFB7F2E2BD03BFA7C280FB6160FB6398D1C023BFB7F1B2BD03BFA7C150FB656FF0FB679FF8D&quot;
        . &quot;1C023BFB7F062BD03BFA7D0A807902000F85930200004583C60483C1043B6C24507CAC8B5C245C8B7424288B4C242403742458FF44247003CBE962FFFF&quot;
        . &quot;FF83F9020F85C60000008B5424108B4C2454498954241C8BD78BF3F7DAF7DE8BF90FAFFB8D7C2F018954242889742424897C2420894C247083F9FF0F8E&quot;
        . &quot;9402000033ED396C24507E798B74241C8B5424648B4C24208D14968B7424488D7432018BFF0FB656010FB679018D1C023BFB7F2E2BD03BFA7C280FB616&quot;
        . &quot;0FB6398D1C023BFB7F1B2BD03BFA7C150FB656FF0FB679FF8D1C023BFB7F062BD03BFA7D0A807902000F85C30100004583C60483C1043B6C24507CAC8B&quot;
        . &quot;7424248B5424288B4C24700154241C4901742420E964FFFFFF83F9030F85D80000008B5424548B4C24104A894C24208BF78BCAF7DE0FAFCB8BFBF7DF89&quot;
        . &quot;742428897C2424894C241C8954247083FAFF0F8EC90100008B6C24504D83FDFF0F8E8B0000008B7424208D14A98B4C244C8D4C0A018B54246403D58D14&quot;
        . &quot;968B7424488D543201EB068D9B000000000FB672010FB679018D1C063BFB7F2E2BF03BFE7C280FB6320FB6398D1C063BFB7F1B2BF03BFE7C150FB672FF&quot;
        . &quot;0FB679FF8D1C063BFB7F062BF03BFE7D0A807902000F85E30000004D83EA0483E90483FDFF7FAD8B7C24248B7424288B4C241C8B542470017424204A03&quot;
        . &quot;CFE94AFFFFFF83F9040F851B0100008B74241433C9894C2470894C24288B4C2470897424243B4C24540F8DFB0000008B6C24504D83FDFF7E738B542428&quot;
        . &quot;8D0CAA8B54244C8D4C11018B54246403D58D14968B7424488D5432010FB672010FB679018D1C063BFB7F2E2BF03BFE7C280FB6320FB6398D1C063BFB7F&quot;
        . &quot;1B2BF03BFE7C150FB672FF0FB679FF8D1C063BFB7F062BF03BFE7D068079020075254D83EA0483E90483FDFF7FB18B5C245C8B74242403742458FF4424&quot;
        . &quot;70015C2428E95CFFFFFF8B5C245C8B6C244C8B7C24588B5424388B4C24648344242C0441894C24643B4C24680F8C91FCFFFF8B74247CFF4424188B4C24&quot;
        . &quot;18017C2410017C2414017C24303B4C246C0F8C2CFCFFFF8B4424408B4C24445F5EC700FFFFFFFF5DC701FFFFFFFF83C8FF5B83C42CC38B5424408B4424&quot;
        . &quot;648B4C24445F89028B5424145E5D891133C05B83C42CC3&quot;
        
        MCode_PixelAverage := &quot;83EC488B4C24608B54246433C0890189028944243C894424388B44245453992BC2558B6C246456578BF88B442468992BC28B54&quot;
        . &quot;24688D5D148D73148D4E14D1FF897E04D1F8894104894308897E088951088B542464897D0C89430C89560C8B54246889510C8B542464897D1089561089&quot;
        . &quot;41108BC52BD92BC18BFE8D51042BF9C74424340100000089542410895C24408944242C897C2430EB178DA424000000008B5424108B5C24408B44242C8B&quot;
        . &quot;7C24308B328B0C1333ED896C2468896C2464896C246C897424443BCE0F8D030100008B0410894424148B0417894424188BC10FAF4424602BF189442438&quot;
        . &quot;8974243C8BFF8B7424148B4C241833DB33FF896C241C896C2420896C2424896C24283BF10F8DA00000002BCE83F9027C538B54245C8D0CB08D4C11018B&quot;
        . &quot;5424182BD683EA02D1EA428D34560FB6410103F80FB60103D80FB641FF0144241C0FB64105014424280FB64104014424240FB641030144242083C1084A&quot;
        . &quot;75CF8B4424388B54241033ED3B7424187D1E8D0CB0034C245C0FB67102017424680FB671010FB60901742464014C246C8B4C24248B7424200374241C03&quot;
        . &quot;CB014C24648B4C24280174246C03CF014C246803442460FF4C243C894424380F852AFFFFFF8B5C24408B44242C8B7C24308B34138B3C172B3C108B0A8B&quot;
        . &quot;4424682BCE0FAFCF33D2F7F133D2896C24688BF88B442464F7F133D28BD88B44246CF7F18D57198954246C8D4B1983C7E783C3E7897C243C894C243889&quot;
        . &quot;5C24288D50198954242483C0E733D2894424203B7424440F8DAE0000008B4424108B4C242C8B0C01894C24148B4C24308B1C018BC60FAF442460895C24&quot;
        . &quot;1C894424648D49008B7C24143BFB7D6B8B4C245C8D04B88D4C080280790100744A0FB6018BDA3B44246C7D063B44243C7F01420FB641FF3B4424387D06&quot;
        . &quot;3B4424287F01420FB641FE3B4424247D063B4424207F01428BC22BC33B4424687E0C897C245089742454894424688B5C241C4783C1043BFB7CA48B4424&quot;
        . &quot;640344246046894424643B7424440F8C7AFFFFFF3B5424487E208B4424708B4C2450895424488B54243489088B4424548954244C8B54247489028B4424&quot;
        . &quot;348344241004408944243483F8050F8C7DFDFFFF8B44244C5F5E5D5B83C448C3&quot;
        
        VarSetCapacity(_ImageSearch1, StrLen(MCode_ImageSearch1)//2, 0)
        Loop % StrLen(MCode_ImageSearch1)//2      ;%
            NumPut(&quot;0x&quot; . SubStr(MCode_ImageSearch1, (2*A_Index)-1, 2), _ImageSearch1, A_Index-1, &quot;uchar&quot;)
        MCode_ImageSearch1 := &quot;&quot;
        
        VarSetCapacity(_ImageSearch2, 1233, 0)
        Loop % StrLen(MCode_ImageSearch2)//2      ;%
            NumPut(&quot;0x&quot; . SubStr(MCode_ImageSearch2, (2*A_Index)-1, 2), _ImageSearch2, A_Index-1, &quot;uchar&quot;)
        MCode_ImageSearch2 := &quot;&quot;
        
        VarSetCapacity(_PixelAverage, StrLen(MCode_PixelAverage)//2, 0)
        Loop % StrLen(MCode_PixelAverage)//2      ;%
            NumPut(&quot;0x&quot; . SubStr(MCode_PixelAverage, (2*A_Index)-1, 2), _PixelAverage, A_Index-1, &quot;uchar&quot;)
        MCode_PixelAverage := &quot;&quot;
        
        , DllCall(&quot;VirtualProtect&quot;, Ptr, &amp;_ImageSearch1, Ptr, VarSetCapacity(_ImageSearch1), &quot;uint&quot;, 0x40, PtrA, 0)
        , DllCall(&quot;VirtualProtect&quot;, Ptr, &amp;_ImageSearch2, Ptr, VarSetCapacity(_ImageSearch2), &quot;uint&quot;, 0x40, PtrA, 0)
        , DllCall(&quot;VirtualProtect&quot;, Ptr, &amp;_PixelAverage, Ptr, VarSetCapacity(_PixelAverage), &quot;uint&quot;, 0x40, PtrA, 0)
    }

    ;The dllcall parameters are the same for easier C code modification even though they arn&#039;t all used on the _ImageSearch1 version
    x := y := suX := suY := 0
    , E := DllCall((Variation = 0 ? &amp;_ImageSearch1 : &amp;_ImageSearch2), &quot;int*&quot;, x, &quot;int*&quot;, y, &quot;ptr&quot;, hScan, &quot;ptr&quot;, nScan, &quot;int&quot;, nWidth
    , &quot;int&quot;, nHeight, &quot;int&quot;, hStride, &quot;int&quot;, nStride, &quot;int&quot;, x1, &quot;int&quot;, y1, &quot;int&quot;, x2, &quot;int&quot;, y2, Ptr, &amp;Trans, &quot;int&quot;, Variation
    , &quot;int&quot;, sd, &quot;int&quot;, suX, &quot;int&quot;, suY, &quot;cdecl int&quot;)
    return (E = &quot;&quot;) ? -13 : E
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Sat, 10 Oct 2020 19:20:29 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142590#p142590</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142578#p142578</link>
			<description><![CDATA[<p>Протестировал.<br />Gdip_FastImageSearch работает быстрее.<br /></p><div class="codebox"><pre><code>needle := &quot;needle.bmp&quot;
x1 := 0, y1 := 0, x2 := 1920, y2 := 1080

f11::
setbatchlines -1

pToken := Gdip_Startup()
pBitmapNeedle := Gdip_CreateBitmapFromFile(needle)
Gdip_GetImageDimensions(pBitmapNeedle, nWidth, nHeight)
Gdip_LockBits(pBitmapNeedle, 0, 0, nWidth, nHeight, nStride, nScan, nBitmapData)

IDXGIFactory := CreateDXGIFactory()
if !IDXGIFactory
{
   MsgBox, 16, Error, Create IDXGIFactory failed.
   ExitApp
}
loop
{
   IDXGIFactory_EnumAdapters(IDXGIFactory, A_Index-1, IDXGIAdapter)
   loop
   {
      hr := IDXGIAdapter_EnumOutputs(IDXGIAdapter, A_Index-1, IDXGIOutput)
      if (hr = &quot;DXGI_ERROR_NOT_FOUND&quot;)
         break
      VarSetCapacity(DXGI_OUTPUT_DESC, 88+A_PtrSize, 0)
      IDXGIOutput_GetDesc(IDXGIOutput, &amp;DXGI_OUTPUT_DESC)
      hWidth := NumGet(DXGI_OUTPUT_DESC, 72, &quot;int&quot;)
      hHeight := NumGet(DXGI_OUTPUT_DESC, 76, &quot;int&quot;)
      AttachedToDesktop := NumGet(DXGI_OUTPUT_DESC, 80, &quot;int&quot;)
      if (AttachedToDesktop = 1)
         break 2         
   }
}
if (AttachedToDesktop != 1)
{
   MsgBox, 16, Error, No adapter attached to desktop
   ExitApp
}
D3D11CreateDevice(IDXGIAdapter, D3D_DRIVER_TYPE_UNKNOWN := 0, 0, 0, 0, 0, D3D11_SDK_VERSION := 7, d3d_device, 0, d3d_context)
IDXGIOutput1 := IDXGIOutput1_Query(IDXGIOutput)
IDXGIOutput1_DuplicateOutput(IDXGIOutput1, d3d_device, Duplication)
VarSetCapacity(DXGI_OUTDUPL_DESC, 36, 0)
IDXGIOutputDuplication_GetDesc(Duplication, &amp;DXGI_OUTDUPL_DESC)
DesktopImageInSystemMemory := NumGet(DXGI_OUTDUPL_DESC, 32, &quot;uint&quot;)
sleep 50   ; As I understand - need some sleep for successful connecting to IDXGIOutputDuplication interface

VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
NumPut(hWidth, D3D11_TEXTURE2D_DESC, 0, &quot;uint&quot;)   ; Width
NumPut(hHeight, D3D11_TEXTURE2D_DESC, 4, &quot;uint&quot;)   ; Height
NumPut(1, D3D11_TEXTURE2D_DESC, 8, &quot;uint&quot;)   ; MipLevels
NumPut(1, D3D11_TEXTURE2D_DESC, 12, &quot;uint&quot;)   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, &quot;uint&quot;)   ; Format 
NumPut(1, D3D11_TEXTURE2D_DESC, 20, &quot;uint&quot;)   ; SampleDescCount
NumPut(0, D3D11_TEXTURE2D_DESC, 24, &quot;uint&quot;)   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, &quot;uint&quot;)   ; Usage
NumPut(0, D3D11_TEXTURE2D_DESC, 32, &quot;uint&quot;)   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, D3D11_TEXTURE2D_DESC, 36, &quot;uint&quot;)   ; CPUAccessFlags
NumPut(0, D3D11_TEXTURE2D_DESC, 40, &quot;uint&quot;)   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &amp;D3D11_TEXTURE2D_DESC, 0, staging_tex)

x2 := ( !x2 ? hWidth-nWidth+1 : x2-nWidth+1 )
y2 := ( !y2 ? hHeight-nHeight+1 : y2-nHeight+1 )

a := a_tickcount
loop 10
{
   tooltip % A_Index
   loop
   {
      VarSetCapacity(DXGI_OUTDUPL_FRAME_INFO, 48, 0)
      AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, INFINITE := 0xFFFFFFFF, &amp;DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
      LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, &quot;int64&quot;)
      if (LastPresentTime != 0)
      {
         if (DesktopImageInSystemMemory = 1)
         {
            VarSetCapacity(DXGI_MAPPED_RECT, A_PtrSize*2, 0)
            IDXGIOutputDuplication_MapDesktopSurface(Duplication, &amp;DXGI_MAPPED_RECT)
            hStride := NumGet(DXGI_MAPPED_RECT, 0, &quot;int&quot;)
            hScan := NumGet(DXGI_MAPPED_RECT, A_PtrSize, &quot;ptr&quot;)
         }
         else
         {
            tex := ID3D11Texture2D_Query(desktop_resource)
            ID3D11DeviceContext_CopyResource(d3d_context, staging_tex, tex)
            VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
            ID3D11DeviceContext_Map(d3d_context, staging_tex, 0, D3D11_MAP_READ := 1, 0, &amp;D3D11_MAPPED_SUBRESOURCE)
            hScan := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, &quot;ptr&quot;)
            hStride := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, &quot;uint&quot;)
         }

;        Gdip_LockedBitsSearch(hStride, hScan, hWidth, hHeight, nStride, nScan, nWidth, nHeight, x, y, x1, y1, x2, y2)
         if !Gdip_FastImageSearch(hStride, hScan, hWidth, hHeight, nStride, nScan, nWidth, nHeight, x, y, x1, y1, x2, y2)
            msgbox % x &quot; - &quot; y

         if (DesktopImageInSystemMemory = 1)
            IDXGIOutputDuplication_UnMapDesktopSurface(Duplication)
         else
         {
            ID3D11DeviceContext_Unmap(d3d_context, staging_tex, 0)
            ObjRelease(tex)
         }
         ObjRelease(desktop_resource)
         IDXGIOutputDuplication_ReleaseFrame(duplication)
         break
      }
      ObjRelease(desktop_resource)
      IDXGIOutputDuplication_ReleaseFrame(duplication)
   }
}
msgbox % a_tickcount - a
Gdip_UnlockBits(pBitmapNeedle, nBitmapData)
Gdip_DisposeImage(pBitmapNeedle)
Release(staging_tex)
Release(d3d_device)
Release(d3d_context)
Release(duplication)
Release(IDXGIAdapter)
Release(IDXGIOutput)
Release(IDXGIOutput1)
Release(IDXGIFactory)
ExitApp














;**********************************************************************************
;
; Gdip_FastImageSearch() - 08/MARCH/2013 21:00h BRT
; by MasterFocus, based on previous work by tic and Rseding91
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition exclusively for these users:
; - tic , Rseding91 , guest3456
;
;**********************************************************************************

;==================================================================================
;
; pBitmapHayStack
;   Use &quot;Screen&quot; or an already existing pBitmap
;   Default: &quot;&quot; (returns -1)
;
; pBitmapNeedle
;   A filename or an already existing pBitmap
;  Default: &quot;&quot; (returns -1)
;
; x and y
;   Variables to store the X and Y coordinates of the image if it&#039;s found
;   Default: &quot;&quot; for both
;
; sx1, sy1, sx2 and sy2
;   These can be used to crop the search area within the haystack
;   Default: &quot;&quot; for all (does not crop)
;
; Variation and Trans
;   Same as the builtin ImageSearch command (I guess we all know that)
;   Default: 0 for both
;
; w and h
;   Parameters used to resize the needle (-1 for one of those will mantain aspect ratio)
;   Default: 0 for both
;
; sd
;   Search direction:
;   0 = auto detect best direction [default]
;   1 = left-&gt;right, top-&gt;bottom ;; 2 = left-&gt;right, bottom-&gt;top
;   3 = right-&gt;left, bottom-&gt;top ;; 4 = right-&gt;left, top-&gt;bottom
;
; UseLastData
;   Tells the function to keep same haystack and/or needle data for future use
;   - If this is set and there is no previous data, the current data is used and saved
;   - If this is not set, any saved data is deleted/released/unlocked
;   0 or 0x00 = not set for the haystack and not set for the needle
;   1 or 0x01 = set for the haystack and not set for the needle
;   2 or 0x10 = not set for the haystack and set for the needle
;   3 or 0x11 = set for the haystack and set for the needle
;   (specially useful for multiple searches with the same haystack and/or needle)
;   Default: 0
;
; nWidth and nHeight
;   These can be used to store, out of the function, the width and height of the needle internally used
;   (retrieved from the resized needle, if w or h is set)
;   (specially useful for multiple searches with the same haystack and/or needle)
;==================================================================================

Gdip_FastImageSearch(hStride, hScan, hWidth, hHeight, nStride, nScan, nWidth, nHeight, ByRef x=&quot;&quot;, ByRef y=&quot;&quot;, x1=&quot;&quot;, y1=&quot;&quot;, x2=&quot;&quot;, y2=&quot;&quot;, Variation=0, Trans=0, sd=1)
{
    static _ImageSearch1, _ImageSearch2, _PixelAverage, Ptr, PtrA
    if !_ImageSearch1
    {
        Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
        , PtrA := A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;
        
        MCode_ImageSearch1 := &quot;8B4C243483EC10803900538B5C2434555657750C80790100750680790200744B8B54243885D27E478B7C2430478BEA908B7424&quot;
        . &quot;3485F67E2C8BC78D9B000000008A50013A510275128A103A5101750B8A50FF3A117504C640020083C0044E75E08B54243803FB4D75C7EB048B5424388B&quot;
        . &quot;4424488944241C3B4424500F8D800200008B4C243C8BF90FAFF88D4402FF0FAFC1897C2418894424148DA424000000008B742444897424543B74244C0F&quot;
        . &quot;8D300200008B74245C83FE0175648B6C243033D2453B5424380F8D5402000033F6397424347E428B4C24548B5C242C8D0C8F8BC58D4C19018A58013A59&quot;
        . &quot;01750E8A183A1975088A58FF3A59FF740A807802000F85B60100004683C10483C0043B7424347CD38B5C2440037C243C4203EBEBA383FE020F85860000&quot;
        . &quot;008BF88BC14A8BCBF7D8F7D98BF20FAFF38B5C243089442410894C24488D6C1E01EB068D9B0000000083FAFF0F8EC701000033F6397424347E468B4C24&quot;
        . &quot;548B5C242C8D0C8F8BC58D4C19018A58013A5901750E8A183A1975088A58FF3A59FF740A807802000F85290100004683C10483C0043B7424347CD38B44&quot;
        . &quot;24108B4C244803F84A03E9EBA283FE030F85840000004A8BFAF7D90FAFFB8BF3F7DE8BE8894C2410897424488D490083FAFF0F8E470100008B44243448&quot;
        . &quot;83F8FF7E518B7424308B5C242C8D0C878D4C31018B74245403F08D74B5008D741E018A59013A5E01750E8A193A1E75088A59FF3A5EFF740A807902000F&quot;
        . &quot;859B0000004883EE0483E90483F8FF7FD48B7424488B4C241003E94A03FEEB9583FE040F85DC00000033ED896C24488D9B00000000395424480F8DC600&quot;
        . &quot;00008B4424344883F8FF7E4D8B4C24308B74242C8D5485008D4C0A018B54245403D08D14978D7432018A51013A5601750E8A113A1675088A51FF3A56FF&quot;
        . &quot;74068079020075224883EE0483E90483F8FF7FD88B5424388B4C243CFF44244803F903EBEB958B5C24408B4424548B7C24188B5424388B4C243C403B44&quot;
        . &quot;244C894424548B4424140F8CD0FDFFFF8B74241C4603C103F98974241C89442414897C24183B7424500F8C9FFDFFFF8B4C24248B5424285F5E5DC701FF&quot;
        . &quot;FFFFFFC702FFFFFFFF83C8FF5B83C410C38B4424248B4C24548B5424285F89088B4424185E5D890233C05B83C410C3&quot;
        
        MCode_ImageSearch2 := &quot;8B4C24348B54241883EC2C803900538B5C2450555657750C80790100750680790200744E8B6C244C85D27E4A8D7D0189542470&quot;
        . &quot;8B74245085F67E298BC78D49008A50013A510275128A103A5101750B8A50FF3A117504C640020083C0044E75E08B6C244C03FBFF4C247075C78B542454&quot;
        . &quot;EB048B6C244C8B442464894424183B44246C0F8D0C0400008B7C24588B74247C8BCF0FAFC8894C24148B8C248000000003C88D4402FF0FAFCF0FAFC789&quot;
        . &quot;4424108B442474894C2430EB068D9B000000008B4C2460894C24643B4C24680F8DA40300008BD30FAF94248000000003D58D0CB20FB611894C24348B4C&quot;
        . &quot;246003CE8B7424308D0C8E034C244889542438894C242CEB048B4C242C0FB6098D34013BD67F062BC83BD17D0E8B4C2434807903000F85350300008B4C&quot;
        . &quot;247883F9010F85AD0000008B742414C7442470000000008D4D018B542470894C2424897424283B5424540F8D5C03000033ED396C24507E698B5424648D&quot;
        . &quot;14968B7424488D7432018BFF0FB656010FB679018D1C023BFB7F2E2BD03BFA7C280FB6160FB6398D1C023BFB7F1B2BD03BFA7C150FB656FF0FB679FF8D&quot;
        . &quot;1C023BFB7F062BD03BFA7D0A807902000F85930200004583C60483C1043B6C24507CAC8B5C245C8B7424288B4C242403742458FF44247003CBE962FFFF&quot;
        . &quot;FF83F9020F85C60000008B5424108B4C2454498954241C8BD78BF3F7DAF7DE8BF90FAFFB8D7C2F018954242889742424897C2420894C247083F9FF0F8E&quot;
        . &quot;9402000033ED396C24507E798B74241C8B5424648B4C24208D14968B7424488D7432018BFF0FB656010FB679018D1C023BFB7F2E2BD03BFA7C280FB616&quot;
        . &quot;0FB6398D1C023BFB7F1B2BD03BFA7C150FB656FF0FB679FF8D1C023BFB7F062BD03BFA7D0A807902000F85C30100004583C60483C1043B6C24507CAC8B&quot;
        . &quot;7424248B5424288B4C24700154241C4901742420E964FFFFFF83F9030F85D80000008B5424548B4C24104A894C24208BF78BCAF7DE0FAFCB8BFBF7DF89&quot;
        . &quot;742428897C2424894C241C8954247083FAFF0F8EC90100008B6C24504D83FDFF0F8E8B0000008B7424208D14A98B4C244C8D4C0A018B54246403D58D14&quot;
        . &quot;968B7424488D543201EB068D9B000000000FB672010FB679018D1C063BFB7F2E2BF03BFE7C280FB6320FB6398D1C063BFB7F1B2BF03BFE7C150FB672FF&quot;
        . &quot;0FB679FF8D1C063BFB7F062BF03BFE7D0A807902000F85E30000004D83EA0483E90483FDFF7FAD8B7C24248B7424288B4C241C8B542470017424204A03&quot;
        . &quot;CFE94AFFFFFF83F9040F851B0100008B74241433C9894C2470894C24288B4C2470897424243B4C24540F8DFB0000008B6C24504D83FDFF7E738B542428&quot;
        . &quot;8D0CAA8B54244C8D4C11018B54246403D58D14968B7424488D5432010FB672010FB679018D1C063BFB7F2E2BF03BFE7C280FB6320FB6398D1C063BFB7F&quot;
        . &quot;1B2BF03BFE7C150FB672FF0FB679FF8D1C063BFB7F062BF03BFE7D068079020075254D83EA0483E90483FDFF7FB18B5C245C8B74242403742458FF4424&quot;
        . &quot;70015C2428E95CFFFFFF8B5C245C8B6C244C8B7C24588B5424388B4C24648344242C0441894C24643B4C24680F8C91FCFFFF8B74247CFF4424188B4C24&quot;
        . &quot;18017C2410017C2414017C24303B4C246C0F8C2CFCFFFF8B4424408B4C24445F5EC700FFFFFFFF5DC701FFFFFFFF83C8FF5B83C42CC38B5424408B4424&quot;
        . &quot;648B4C24445F89028B5424145E5D891133C05B83C42CC3&quot;
        
        MCode_PixelAverage := &quot;83EC488B4C24608B54246433C0890189028944243C894424388B44245453992BC2558B6C246456578BF88B442468992BC28B54&quot;
        . &quot;24688D5D148D73148D4E14D1FF897E04D1F8894104894308897E088951088B542464897D0C89430C89560C8B54246889510C8B542464897D1089561089&quot;
        . &quot;41108BC52BD92BC18BFE8D51042BF9C74424340100000089542410895C24408944242C897C2430EB178DA424000000008B5424108B5C24408B44242C8B&quot;
        . &quot;7C24308B328B0C1333ED896C2468896C2464896C246C897424443BCE0F8D030100008B0410894424148B0417894424188BC10FAF4424602BF189442438&quot;
        . &quot;8974243C8BFF8B7424148B4C241833DB33FF896C241C896C2420896C2424896C24283BF10F8DA00000002BCE83F9027C538B54245C8D0CB08D4C11018B&quot;
        . &quot;5424182BD683EA02D1EA428D34560FB6410103F80FB60103D80FB641FF0144241C0FB64105014424280FB64104014424240FB641030144242083C1084A&quot;
        . &quot;75CF8B4424388B54241033ED3B7424187D1E8D0CB0034C245C0FB67102017424680FB671010FB60901742464014C246C8B4C24248B7424200374241C03&quot;
        . &quot;CB014C24648B4C24280174246C03CF014C246803442460FF4C243C894424380F852AFFFFFF8B5C24408B44242C8B7C24308B34138B3C172B3C108B0A8B&quot;
        . &quot;4424682BCE0FAFCF33D2F7F133D2896C24688BF88B442464F7F133D28BD88B44246CF7F18D57198954246C8D4B1983C7E783C3E7897C243C894C243889&quot;
        . &quot;5C24288D50198954242483C0E733D2894424203B7424440F8DAE0000008B4424108B4C242C8B0C01894C24148B4C24308B1C018BC60FAF442460895C24&quot;
        . &quot;1C894424648D49008B7C24143BFB7D6B8B4C245C8D04B88D4C080280790100744A0FB6018BDA3B44246C7D063B44243C7F01420FB641FF3B4424387D06&quot;
        . &quot;3B4424287F01420FB641FE3B4424247D063B4424207F01428BC22BC33B4424687E0C897C245089742454894424688B5C241C4783C1043BFB7CA48B4424&quot;
        . &quot;640344246046894424643B7424440F8C7AFFFFFF3B5424487E208B4424708B4C2450895424488B54243489088B4424548954244C8B54247489028B4424&quot;
        . &quot;348344241004408944243483F8050F8C7DFDFFFF8B44244C5F5E5D5B83C448C3&quot;
        
        VarSetCapacity(_ImageSearch1, StrLen(MCode_ImageSearch1)//2, 0)
        Loop % StrLen(MCode_ImageSearch1)//2      ;%
            NumPut(&quot;0x&quot; . SubStr(MCode_ImageSearch1, (2*A_Index)-1, 2), _ImageSearch1, A_Index-1, &quot;uchar&quot;)
        MCode_ImageSearch1 := &quot;&quot;
        
        VarSetCapacity(_ImageSearch2, 1233, 0)
        Loop % StrLen(MCode_ImageSearch2)//2      ;%
            NumPut(&quot;0x&quot; . SubStr(MCode_ImageSearch2, (2*A_Index)-1, 2), _ImageSearch2, A_Index-1, &quot;uchar&quot;)
        MCode_ImageSearch2 := &quot;&quot;
        
        VarSetCapacity(_PixelAverage, StrLen(MCode_PixelAverage)//2, 0)
        Loop % StrLen(MCode_PixelAverage)//2      ;%
            NumPut(&quot;0x&quot; . SubStr(MCode_PixelAverage, (2*A_Index)-1, 2), _PixelAverage, A_Index-1, &quot;uchar&quot;)
        MCode_PixelAverage := &quot;&quot;
        
        , DllCall(&quot;VirtualProtect&quot;, Ptr, &amp;_ImageSearch1, Ptr, VarSetCapacity(_ImageSearch1), &quot;uint&quot;, 0x40, PtrA, 0)
        , DllCall(&quot;VirtualProtect&quot;, Ptr, &amp;_ImageSearch2, Ptr, VarSetCapacity(_ImageSearch2), &quot;uint&quot;, 0x40, PtrA, 0)
        , DllCall(&quot;VirtualProtect&quot;, Ptr, &amp;_PixelAverage, Ptr, VarSetCapacity(_PixelAverage), &quot;uint&quot;, 0x40, PtrA, 0)
    }

    ;The dllcall parameters are the same for easier C code modification even though they arn&#039;t all used on the _ImageSearch1 version
    x := y := suX := suY := 0
    , E := DllCall((Variation = 0 ? &amp;_ImageSearch1 : &amp;_ImageSearch2), &quot;int*&quot;, x, &quot;int*&quot;, y, &quot;ptr&quot;, hScan, &quot;ptr&quot;, nScan, &quot;int&quot;, nWidth
    , &quot;int&quot;, nHeight, &quot;int&quot;, hStride, &quot;int&quot;, nStride, &quot;int&quot;, x1, &quot;int&quot;, y1, &quot;int&quot;, x2, &quot;int&quot;, y2, Ptr, &amp;Trans, &quot;int&quot;, Variation
    , &quot;int&quot;, sd, &quot;int&quot;, suX, &quot;int&quot;, suY, &quot;cdecl int&quot;)
    return (E = &quot;&quot;) ? -13 : E
}












CreateDXGIFactory()
{
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;DXGI&quot;)
      DllCall(&quot;LoadLibrary&quot;,&quot;str&quot;,&quot;DXGI&quot;)
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;D3D11&quot;)
      DllCall(&quot;LoadLibrary&quot;,&quot;str&quot;,&quot;D3D11&quot;)
   GUID(riid, &quot;{7b7166ec-21c7-44ae-b21a-c9ae321ae369}&quot;)
   hr := DllCall(&quot;DXGI\CreateDXGIFactory1&quot;, &quot;ptr&quot;, &amp;riid, &quot;ptr*&quot;, ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return ppFactory
}

IDXGIFactory_EnumAdapters(this, Adapter, ByRef ppAdapter)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), &quot;ptr&quot;, this, &quot;uint&quot;, Adapter, &quot;ptr*&quot;, ppAdapter)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

IDXGIAdapter_EnumOutputs(this, Output, ByRef ppOutput)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), &quot;ptr&quot;, this, &quot;uint&quot;, Output, &quot;ptr*&quot;, ppOutput)
   if hr or ErrorLevel
   {
      if (hr&amp;=0xFFFFFFFF) = 0x887A0002   ; DXGI_ERROR_NOT_FOUND
         return &quot;DXGI_ERROR_NOT_FOUND&quot;
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   }
}

IDXGIAdapter_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*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)
}

IDXGIOutput_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*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)
}

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

IDXGIOutputDuplication_AcquireNextFrame(this, TimeoutInMilliseconds, pFrameInfo, ByRef ppDesktopResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), &quot;ptr&quot;, this, &quot;uint&quot;, TimeoutInMilliseconds, &quot;ptr&quot;, pFrameInfo, &quot;ptr*&quot;, ppDesktopResource)
   if hr or ErrorLevel
   {
      if (hr&amp;=0xFFFFFFFF) = 0x887A0027   ; DXGI_ERROR_WAIT_TIMEOUT
         return &quot;DXGI_ERROR_WAIT_TIMEOUT&quot;
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   }
}

D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ByRef ppDevice, ByRef pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall(&quot;D3D11\D3D11CreateDevice&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;, ppDevice, &quot;ptr*&quot;, pFeatureLevel, &quot;ptr*&quot;, ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

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

IDXGIOutputDuplication_MapDesktopSurface(this, pLockedRect)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pLockedRect)
   if hr or ErrorLevel
   {
      if (hr&amp;=0xFFFFFFFF) = 0x887A0004   ; DXGI_ERROR_UNSUPPORTED
         return &quot;DXGI_ERROR_UNSUPPORTED&quot;
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   }
}

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

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

IDXGIOutput1_DuplicateOutput(this, pDevice, ByRef ppOutputDuplication)
{
   hr := DllCall(NumGet(NumGet(this+0)+22*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDevice, &quot;ptr*&quot;, ppOutputDuplication)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

IDXGIOutput1_Query(IDXGIOutput)
{ 
   hr := ComObjQuery(IDXGIOutput, &quot;{00cddea8-939b-4b83-a340-a685226666cc}&quot;)
   if !hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return hr
}

ID3D11Texture2D_Query(desktop_resource)
{ 
   hr := ComObjQuery(desktop_resource, &quot;{6f15aaf2-d208-4e89-9ab4-489535d34f9c}&quot;)
   if !hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return hr
}

ID3D11DeviceContext_CopyResource(this, pDstResource, pSrcResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+47*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDstResource, &quot;ptr&quot;, pSrcResource)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11DeviceContext_CopySubresourceRegion(this, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox)
{
   hr := DllCall(NumGet(NumGet(this+0)+46*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDstResource, &quot;uint&quot;, DstSubresource, &quot;uint&quot;, DstX, &quot;uint&quot;, DstY, &quot;uint&quot;, DstZ, &quot;ptr&quot;, pSrcResource, &quot;uint&quot;, SrcSubresource, &quot;ptr&quot;, pSrcBox)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11DeviceContext_Map(this, pResource, Subresource, MapType, MapFlags, pMappedResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pResource, &quot;uint&quot;, Subresource, &quot;uint&quot;, MapType, &quot;uint&quot;, MapFlags, &quot;ptr&quot;, pMappedResource)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11DeviceContext_Unmap(this, pResource, Subresource)
{
   hr := DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pResource, &quot;uint&quot;, Subresource)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

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
}










;**********************************************************************************
;
; Gdip_ImageSearch()
; by MasterFocus - 02/APRIL/2013 00:30h BRT
; Thanks to guest3456 for helping me ponder some ideas
; Requires GDIP, Gdip_SetBitmapTransColor() and Gdip_MultiLockedBitsSearch()
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition of the license EXCLUSIVELY
; for these users: tic , Rseding91 , guest3456
;
;==================================================================================
;
; This function searches for pBitmapNeedle within pBitmapHaystack
; The returned value is the number of instances found (negative = error)
;
; ++ PARAMETERS ++
;
; pBitmapHaystack and pBitmapNeedle
;   Self-explanatory bitmap pointers, are the only required parameters
;
; OutputList
;   ByRef variable to store the list of coordinates where a match was found
;
; OuterX1, OuterY1, OuterX2, OuterY2
;   Equivalent to ImageSearch&#039;s X1,Y1,X2,Y2
;   Default: 0 for all (which searches the whole haystack area)
;
; Variation
;   Just like ImageSearch, a value from 0 to 255
;   Default: 0
;
; Trans
;   Needle RGB transparent color, should be a numerical value from 0 to 0xFFFFFF
;   Default: blank (does not use transparency)
;
; SearchDirection
;   Haystack search direction
;     Vertical preference:
;       1 = top-&gt;left-&gt;right-&gt;bottom [default]
;       2 = bottom-&gt;left-&gt;right-&gt;top
;       3 = bottom-&gt;right-&gt;left-&gt;top
;       4 = top-&gt;right-&gt;left-&gt;bottom
;     Horizontal preference:
;       5 = left-&gt;top-&gt;bottom-&gt;right
;       6 = left-&gt;bottom-&gt;top-&gt;right
;       7 = right-&gt;bottom-&gt;top-&gt;left
;       8 = right-&gt;top-&gt;bottom-&gt;left
;
; Instances
;   Maximum number of instances to find when searching (0 = find all)
;   Default: 1 (stops after one match is found)
;
; LineDelim and CoordDelim
;   Outer and inner delimiters for the list of coordinates (OutputList)
;   Defaults: &quot;`n&quot; and &quot;,&quot;
;
; ++ RETURN VALUES ++
;
; -1001 ==&gt; invalid haystack and/or needle bitmap pointer
; -1002 ==&gt; invalid variation value
; -1003 ==&gt; X1 and Y1 cannot be negative
; -1004 ==&gt; unable to lock haystack bitmap bits
; -1005 ==&gt; unable to lock needle bitmap bits
; any non-negative value ==&gt; the number of instances found
;
;==================================================================================
;
;**********************************************************************************

Gdip_ImageSearch(pBitmapHaystack,pBitmapNeedle,ByRef OutputList=&quot;&quot;,OuterX1=0,OuterY1=0,OuterX2=0,OuterY2=0,Variation=0,Trans=&quot;&quot;,SearchDirection=1,Instances=1,LineDelim=&quot;`n&quot;,CoordDelim=&quot;,&quot;) {
    ; Some validations that can be done before proceeding any further
    If !( pBitmapHaystack &amp;&amp; pBitmapNeedle )
        Return -1001
    If Variation not between 0 and 255
        return -1002
    If ( ( OuterX1 &lt; 0 ) || ( OuterY1 &lt; 0 ) )
        return -1003
    If SearchDirection not between 1 and 8
        SearchDirection := 1
    If ( Instances &lt; 0 )
        Instances := 0

    ; Getting the dimensions and locking the bits [haystack]
    Gdip_GetImageDimensions(pBitmapHaystack,hWidth,hHeight)
    ; Last parameter being 1 says the LockMode flag is &quot;READ only&quot;
    If Gdip_LockBits(pBitmapHaystack,0,0,hWidth,hHeight,hStride,hScan,hBitmapData,1)
    OR !(hWidth := NumGet(hBitmapData,0,&quot;UInt&quot;))
    OR !(hHeight := NumGet(hBitmapData,4,&quot;UInt&quot;))
        Return -1004

    ; Careful! From this point on, we must do the following before returning:
    ; - unlock haystack bits

    ; Getting the dimensions and locking the bits [needle]
    Gdip_GetImageDimensions(pBitmapNeedle,nWidth,nHeight)
    ; If Trans is correctly specified, create a backup of the original needle bitmap
    ; and modify the current one, setting the desired color as transparent.
    ; Also, since a copy is created, we must remember to dispose the new bitmap later.
    ; This whole thing has to be done before locking the bits.
    If Trans between 0 and 0xFFFFFF
    {
        pOriginalBmpNeedle := pBitmapNeedle
        pBitmapNeedle := Gdip_CloneBitmapArea(pOriginalBmpNeedle,0,0,nWidth,nHeight)
        Gdip_SetBitmapTransColor(pBitmapNeedle,Trans)
        DumpCurrentNeedle := true
    }

    ; Careful! From this point on, we must do the following before returning:
    ; - unlock haystack bits
    ; - dispose current needle bitmap (if necessary)

    If Gdip_LockBits(pBitmapNeedle,0,0,nWidth,nHeight,nStride,nScan,nBitmapData)
    OR !(nWidth := NumGet(nBitmapData,0,&quot;UInt&quot;))
    OR !(nHeight := NumGet(nBitmapData,4,&quot;UInt&quot;))
    {
        If ( DumpCurrentNeedle )
            Gdip_DisposeImage(pBitmapNeedle)
        Gdip_UnlockBits(pBitmapHaystack,hBitmapData)
        Return -1005
    }
    
    ; Careful! From this point on, we must do the following before returning:
    ; - unlock haystack bits
    ; - unlock needle bits
    ; - dispose current needle bitmap (if necessary)

    ; Adjust the search box. &quot;OuterX2,OuterY2&quot; will be the last pixel evaluated
    ; as possibly matching with the needle&#039;s first pixel. So, we must avoid going
    ; beyond this maximum final coordinate.
    OuterX2 := ( !OuterX2 ? hWidth-nWidth+1 : OuterX2-nWidth+1 )
    OuterY2 := ( !OuterY2 ? hHeight-nHeight+1 : OuterY2-nHeight+1 )

    OutputCount := Gdip_MultiLockedBitsSearch(hStride,hScan,hWidth,hHeight
    ,nStride,nScan,nWidth,nHeight,OutputList,OuterX1,OuterY1,OuterX2,OuterY2
    ,Variation,SearchDirection,Instances,LineDelim,CoordDelim)

    Gdip_UnlockBits(pBitmapHaystack,hBitmapData)
    Gdip_UnlockBits(pBitmapNeedle,nBitmapData)
    If ( DumpCurrentNeedle )
        Gdip_DisposeImage(pBitmapNeedle)

    Return OutputCount
}

;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

;**********************************************************************************
;
; Gdip_SetBitmapTransColor()
; by MasterFocus - 02/APRIL/2013 00:30h BRT
; Requires GDIP
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition of the license EXCLUSIVELY
; for these users: tic , Rseding91 , guest3456
;
;**********************************************************************************

;==================================================================================
;
; This function modifies the Alpha component for all pixels of a certain color to 0
; The returned value is 0 in case of success, or a negative number otherwise
;
; ++ PARAMETERS ++
;
; pBitmap
;   A valid pointer to the bitmap that will be modified
;
; TransColor
;   The color to become transparent
;   Should range from 0 (black) to 0xFFFFFF (white)
;
; ++ RETURN VALUES ++
;
; -2001 ==&gt; invalid bitmap pointer
; -2002 ==&gt; invalid TransColor
; -2003 ==&gt; unable to retrieve bitmap positive dimensions
; -2004 ==&gt; unable to lock bitmap bits
; -2005 ==&gt; DllCall failed (see ErrorLevel)
; any non-negative value ==&gt; the number of pixels modified by this function
;
;==================================================================================

Gdip_SetBitmapTransColor(pBitmap,TransColor) {
    static _SetBmpTrans, Ptr, PtrA
    if !( _SetBmpTrans ) {
        Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
        PtrA := Ptr . &quot;*&quot;
        MCode_SetBmpTrans := &quot;
            (LTrim Join
            8b44240c558b6c241cc745000000000085c07e77538b5c2410568b74242033c9578b7c2414894c24288da424000000
            0085db7e458bc18d1439b9020000008bff8a0c113a4e0275178a4c38013a4e01750e8a0a3a0e7508c644380300ff450083c0
            0483c204b9020000004b75d38b4c24288b44241c8b5c2418034c242048894c24288944241c75a85f5e5b33c05dc3,405
            34c8b5424388bda41c702000000004585c07e6448897c2410458bd84c8b4424304963f94c8d49010f1f800000000085db7e3
            8498bc1488bd3660f1f440000410fb648023848017519410fb6480138087510410fb6083848ff7507c640020041ff024883c
            00448ffca75d44c03cf49ffcb75bc488b7c241033c05bc3
            )&quot;
        if ( A_PtrSize == 8 ) ; x64, after comma
            MCode_SetBmpTrans := SubStr(MCode_SetBmpTrans,InStr(MCode_SetBmpTrans,&quot;,&quot;)+1)
        else ; x86, before comma
            MCode_SetBmpTrans := SubStr(MCode_SetBmpTrans,1,InStr(MCode_SetBmpTrans,&quot;,&quot;)-1)
        VarSetCapacity(_SetBmpTrans, LEN := StrLen(MCode_SetBmpTrans)//2, 0)
        Loop, %LEN%
            NumPut(&quot;0x&quot; . SubStr(MCode_SetBmpTrans,(2*A_Index)-1,2), _SetBmpTrans, A_Index-1, &quot;uchar&quot;)
        MCode_SetBmpTrans := &quot;&quot;
        DllCall(&quot;VirtualProtect&quot;, Ptr,&amp;_SetBmpTrans, Ptr,VarSetCapacity(_SetBmpTrans), &quot;uint&quot;,0x40, PtrA,0)
    }
    If !pBitmap
        Return -2001
    If TransColor not between 0 and 0xFFFFFF
        Return -2002
    Gdip_GetImageDimensions(pBitmap,W,H)
    If !(W &amp;&amp; H)
        Return -2003
    If Gdip_LockBits(pBitmap,0,0,W,H,Stride,Scan,BitmapData)
        Return -2004
    ; The following code should be slower than using the MCode approach,
    ; but will the kept here for now, just for reference.
    /*
    Count := 0
    Loop, %H% {
        Y := A_Index-1
        Loop, %W% {
            X := A_Index-1
            CurrentColor := Gdip_GetLockBitPixel(Scan,X,Y,Stride)
            If ( (CurrentColor &amp; 0xFFFFFF) == TransColor )
                Gdip_SetLockBitPixel(TransColor,Scan,X,Y,Stride), Count++
        }
    }
    */
    ; Thanks guest3456 for helping with the initial solution involving NumPut
    Gdip_FromARGB(TransColor,A,R,G,B), VarSetCapacity(TransColor,0), VarSetCapacity(TransColor,3,255)
    NumPut(B,TransColor,0,&quot;UChar&quot;), NumPut(G,TransColor,1,&quot;UChar&quot;), NumPut(R,TransColor,2,&quot;UChar&quot;)
    MCount := 0
    E := DllCall(&amp;_SetBmpTrans, Ptr,Scan, &quot;int&quot;,W, &quot;int&quot;,H, &quot;int&quot;,Stride, Ptr,&amp;TransColor, &quot;int*&quot;,MCount, &quot;cdecl int&quot;)
    Gdip_UnlockBits(pBitmap,BitmapData)
    If ( E != 0 ) {
        ErrorLevel := E
        Return -2005
    }
    Return MCount
}

;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

;**********************************************************************************
;
; Gdip_MultiLockedBitsSearch()
; by MasterFocus - 24/MARCH/2013 06:20h BRT
; Requires GDIP and Gdip_LockedBitsSearch()
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition of the license EXCLUSIVELY
; for these users: tic , Rseding91 , guest3456
;
;**********************************************************************************

;==================================================================================
;
; This function returns the number of instances found
; The 8 first parameters are the same as in Gdip_LockedBitsSearch()
; The other 10 parameters are the same as in Gdip_ImageSearch()
; Note: the default for the Intances parameter here is 0 (find all matches)
;
;==================================================================================

Gdip_MultiLockedBitsSearch(hStride,hScan,hWidth,hHeight,nStride,nScan,nWidth,nHeight
,ByRef OutputList=&quot;&quot;,OuterX1=0,OuterY1=0,OuterX2=0,OuterY2=0,Variation=0
,SearchDirection=1,Instances=0,LineDelim=&quot;`n&quot;,CoordDelim=&quot;,&quot;)
{
    OutputList := &quot;&quot;
    OutputCount := !Instances
    InnerX1 := OuterX1 , InnerY1 := OuterY1
    InnerX2 := OuterX2 , InnerY2 := OuterY2

    ; The following part is a rather ugly but working hack that I
    ; came up with to adjust the variables and their increments
    ; according to the specified Haystack Search Direction
    /*
    Mod(SD,4) = 0 --&gt; iX = 2 , stepX = +0 , iY = 1 , stepY = +1
    Mod(SD,4) = 1 --&gt; iX = 1 , stepX = +1 , iY = 1 , stepY = +1
    Mod(SD,4) = 2 --&gt; iX = 1 , stepX = +1 , iY = 2 , stepY = +0
    Mod(SD,4) = 3 --&gt; iX = 2 , stepX = +0 , iY = 2 , stepY = +0
    SD &lt;= 4   ------&gt; Vertical preference
    SD &gt; 4    ------&gt; Horizontal preference
    */
    ; Set the index and the step (for both X and Y) to +1
    iX := 1, stepX := 1, iY := 1, stepY := 1
    ; Adjust Y variables if SD is 2, 3, 6 or 7
    Modulo := Mod(SearchDirection,4)
    If ( Modulo &gt; 1 )
        iY := 2, stepY := 0
    ; adjust X variables if SD is 3, 4, 7 or 8
    If !Mod(Modulo,3)
        iX := 2, stepX := 0
    ; Set default Preference to vertical and Nonpreference to horizontal
    P := &quot;Y&quot;, N := &quot;X&quot;
    ; adjust Preference and Nonpreference if SD is 5, 6, 7 or 8
    If ( SearchDirection &gt; 4 )
        P := &quot;X&quot;, N := &quot;Y&quot;
    ; Set the Preference Index and the Nonpreference Index
    iP := i%P%, iN := i%N%

    While (!(OutputCount == Instances) &amp;&amp; (0 == Gdip_LockedBitsSearch(hStride,hScan,hWidth,hHeight,nStride
    ,nScan,nWidth,nHeight,FoundX,FoundY,OuterX1,OuterY1,OuterX2,OuterY2,Variation,SearchDirection)))
    {
        OutputCount++
        OutputList .= LineDelim FoundX CoordDelim FoundY
        Outer%P%%iP% := Found%P%+step%P%
        Inner%N%%iN% := Found%N%+step%N%
        Inner%P%1 := Found%P%
        Inner%P%2 := Found%P%+1
        While (!(OutputCount == Instances) &amp;&amp; (0 == Gdip_LockedBitsSearch(hStride,hScan,hWidth,hHeight,nStride
        ,nScan,nWidth,nHeight,FoundX,FoundY,InnerX1,InnerY1,InnerX2,InnerY2,Variation,SearchDirection)))
        {
            OutputCount++
            OutputList .= LineDelim FoundX CoordDelim FoundY
            Inner%N%%iN% := Found%N%+step%N%
        }
    }
    OutputList := SubStr(OutputList,1+StrLen(LineDelim))
    OutputCount -= !Instances
    Return OutputCount
}

;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

;**********************************************************************************
;
; Gdip_LockedBitsSearch()
; by MasterFocus - 24/MARCH/2013 06:20h BRT
; Mostly adapted from previous work by tic and Rseding91
;
; Requires GDIP
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition of the license EXCLUSIVELY
; for these users: tic , Rseding91 , guest3456
;
;**********************************************************************************

;==================================================================================
;
; This function searches for a single match of nScan within hScan
;
; ++ PARAMETERS ++
;
; hStride, hScan, hWidth and hHeight
;   Haystack stuff, extracted from a BitmapData, extracted from a Bitmap
;
; nStride, nScan, nWidth and nHeight
;   Needle stuff, extracted from a BitmapData, extracted from a Bitmap
;
; x and y
;   ByRef variables to store the X and Y coordinates of the image if it&#039;s found
;   Default: &quot;&quot; for both
;
; sx1, sy1, sx2 and sy2
;   These can be used to crop the search area within the haystack
;   Default: &quot;&quot; for all (does not crop)
;
; Variation
;   Same as the builtin ImageSearch command
;   Default: 0
;
; sd
;   Haystack search direction
;     Vertical preference:
;       1 = top-&gt;left-&gt;right-&gt;bottom [default]
;       2 = bottom-&gt;left-&gt;right-&gt;top
;       3 = bottom-&gt;right-&gt;left-&gt;top
;       4 = top-&gt;right-&gt;left-&gt;bottom
;     Horizontal preference:
;       5 = left-&gt;top-&gt;bottom-&gt;right
;       6 = left-&gt;bottom-&gt;top-&gt;right
;       7 = right-&gt;bottom-&gt;top-&gt;left
;       8 = right-&gt;top-&gt;bottom-&gt;left
;   This value is passed to the internal MCoded function
;
; ++ RETURN VALUES ++
;
; -3001 to -3006 ==&gt; search area incorrectly defined
; -3007 ==&gt; DllCall returned blank
; 0 ==&gt; DllCall succeeded and a match was found
; -4001 ==&gt; DllCall succeeded but a match was not found
; anything else ==&gt; the error value returned by the unsuccessful DllCall
;
;==================================================================================

Gdip_LockedBitsSearch(hStride,hScan,hWidth,hHeight,nStride,nScan,nWidth,nHeight
,ByRef x=&quot;&quot;,ByRef y=&quot;&quot;,sx1=0,sy1=0,sx2=0,sy2=0,Variation=0,sd=1)
{
    static _ImageSearch, Ptr, PtrA

    ; Initialize all MCode stuff, if necessary
    if !( _ImageSearch ) {
        Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
        PtrA := Ptr . &quot;*&quot;

        MCode_ImageSearch := &quot;
            (LTrim Join
            8b44243883ec205355565783f8010f857a0100008b7c2458897c24143b7c24600f8db50b00008b44244c8b5c245c8b
            4c24448b7424548be80fafef896c242490897424683bf30f8d0a0100008d64240033c033db8bf5896c241c895c2420894424
            183b4424480f8d0401000033c08944241085c90f8e9d0000008b5424688b7c24408beb8d34968b54246403df8d4900b80300
            0000803c18008b442410745e8b44243c0fb67c2f020fb64c06028d04113bf87f792bca3bf97c738b44243c0fb64c06018b44
            24400fb67c28018d04113bf87f5a2bca3bf97c548b44243c0fb63b0fb60c068d04113bf87f422bca3bf97c3c8b4424108b7c
            24408b4c24444083c50483c30483c604894424103bc17c818b5c24208b74241c0374244c8b44241840035c24508974241ce9
            2dffffff8b6c24688b5c245c8b4c244445896c24683beb8b6c24240f8c06ffffff8b44244c8b7c24148b7424544703e8897c
            2414896c24243b7c24600f8cd5feffffe96b0a00008b4424348b4c246889088b4424388b4c24145f5e5d890833c05b83c420
            c383f8020f85870100008b7c24604f897c24103b7c24580f8c310a00008b44244c8b5c245c8b4c24448bef0fafe8f7d88944
            24188b4424548b742418896c24288d4900894424683bc30f8d0a0100008d64240033c033db8bf5896c2420895c241c894424
            243b4424480f8d0401000033c08944241485c90f8e9d0000008b5424688b7c24408beb8d34968b54246403df8d4900b80300
            0000803c03008b442414745e8b44243c0fb67c2f020fb64c06028d04113bf87f792bca3bf97c738b44243c0fb64c06018b44
            24400fb67c28018d04113bf87f5a2bca3bf97c548b44243c0fb63b0fb60c068d04113bf87f422bca3bf97c3c8b4424148b7c
            24408b4c24444083c50483c30483c604894424143bc17c818b5c241c8b7424200374244c8b44242440035c245089742420e9
            2dffffff8b6c24688b5c245c8b4c244445896c24683beb8b6c24280f8c06ffffff8b7c24108b4424548b7424184f03ee897c
            2410896c24283b7c24580f8dd5feffffe9db0800008b4424348b4c246889088b4424388b4c24105f5e5d890833c05b83c420
            c383f8030f85650100008b7c24604f897c24103b7c24580f8ca10800008b44244c8b6c245c8b5c24548b4c24448bf70faff0
            4df7d8896c242c897424188944241c8bff896c24683beb0f8c020100008d64240033c033db89742424895c2420894424283b
            4424480f8d76ffffff33c08944241485c90f8e9f0000008b5424688b7c24408beb8d34968b54246403dfeb038d4900b80300
            0000803c03008b442414745e8b44243c0fb67c2f020fb64c06028d04113bf87f752bca3bf97c6f8b44243c0fb64c06018b44
            24400fb67c28018d04113bf87f562bca3bf97c508b44243c0fb63b0fb60c068d04113bf87f3e2bca3bf97c388b4424148b7c
            24408b4c24444083c50483c30483c604894424143bc17c818b5c24208b7424248b4424280374244c40035c2450e92bffffff
            8b6c24688b5c24548b4c24448b7424184d896c24683beb0f8d0affffff8b7c24108b44241c4f03f0897c2410897424183b7c
            24580f8c580700008b6c242ce9d4feffff83f8040f85670100008b7c2458897c24103b7c24600f8d340700008b44244c8b6c
            245c8b5c24548b4c24444d8bf00faff7896c242c8974241ceb098da424000000008bff896c24683beb0f8c020100008d6424
            0033c033db89742424895c2420894424283b4424480f8d06feffff33c08944241485c90f8e9f0000008b5424688b7c24408b
            eb8d34968b54246403dfeb038d4900b803000000803c03008b442414745e8b44243c0fb67c2f020fb64c06028d04113bf87f
            752bca3bf97c6f8b44243c0fb64c06018b4424400fb67c28018d04113bf87f562bca3bf97c508b44243c0fb63b0fb60c068d
            04113bf87f3e2bca3bf97c388b4424148b7c24408b4c24444083c50483c30483c604894424143bc17c818b5c24208b742424
            8b4424280374244c40035c2450e92bffffff8b6c24688b5c24548b4c24448b74241c4d896c24683beb0f8d0affffff8b4424
            4c8b7c24104703f0897c24108974241c3b7c24600f8de80500008b6c242ce9d4feffff83f8050f85890100008b7c2454897c
            24683b7c245c0f8dc40500008b5c24608b6c24588b44244c8b4c2444eb078da42400000000896c24103beb0f8d200100008b
            e80faf6c2458896c241c33c033db8bf5896c2424895c2420894424283b4424480f8d0d01000033c08944241485c90f8ea600
            00008b5424688b7c24408beb8d34968b54246403dfeb0a8da424000000008d4900b803000000803c03008b442414745e8b44
            243c0fb67c2f020fb64c06028d04113bf87f792bca3bf97c738b44243c0fb64c06018b4424400fb67c28018d04113bf87f5a
            2bca3bf97c548b44243c0fb63b0fb60c068d04113bf87f422bca3bf97c3c8b4424148b7c24408b4c24444083c50483c30483
            c604894424143bc17c818b5c24208b7424240374244c8b44242840035c245089742424e924ffffff8b7c24108b6c241c8b44
            244c8b5c24608b4c24444703e8897c2410896c241c3bfb0f8cf3feffff8b7c24688b6c245847897c24683b7c245c0f8cc5fe
            ffffe96b0400008b4424348b4c24688b74241089088b4424385f89305e5d33c05b83c420c383f8060f85670100008b7c2454
            897c24683b7c245c0f8d320400008b6c24608b5c24588b44244c8b4c24444d896c24188bff896c24103beb0f8c1a0100008b
            f50faff0f7d88974241c8944242ceb038d490033c033db89742424895c2420894424283b4424480f8d06fbffff33c0894424
            1485c90f8e9f0000008b5424688b7c24408beb8d34968b54246403dfeb038d4900b803000000803c03008b442414745e8b44
            243c0fb67c2f020fb64c06028d04113bf87f752bca3bf97c6f8b44243c0fb64c06018b4424400fb67c28018d04113bf87f56
            2bca3bf97c508b44243c0fb63b0fb60c068d04113bf87f3e2bca3bf97c388b4424148b7c24408b4c24444083c50483c30483
            c604894424143bc17c818b5c24208b7424248b4424280374244c40035c2450e92bffffff8b6c24108b74241c0374242c8b5c
            24588b4c24444d896c24108974241c3beb0f8d02ffffff8b44244c8b7c246847897c24683b7c245c0f8de60200008b6c2418
            e9c2feffff83f8070f85670100008b7c245c4f897c24683b7c24540f8cc10200008b6c24608b5c24588b44244c8b4c24444d
            896c241890896c24103beb0f8c1a0100008bf50faff0f7d88974241c8944242ceb038d490033c033db89742424895c242089
            4424283b4424480f8d96f9ffff33c08944241485c90f8e9f0000008b5424688b7c24408beb8d34968b54246403dfeb038d49
            00b803000000803c18008b442414745e8b44243c0fb67c2f020fb64c06028d04113bf87f752bca3bf97c6f8b44243c0fb64c
            06018b4424400fb67c28018d04113bf87f562bca3bf97c508b44243c0fb63b0fb60c068d04113bf87f3e2bca3bf97c388b44
            24148b7c24408b4c24444083c50483c30483c604894424143bc17c818b5c24208b7424248b4424280374244c40035c2450e9
            2bffffff8b6c24108b74241c0374242c8b5c24588b4c24444d896c24108974241c3beb0f8d02ffffff8b44244c8b7c24684f
            897c24683b7c24540f8c760100008b6c2418e9c2feffff83f8080f85640100008b7c245c4f897c24683b7c24540f8c510100
            008b5c24608b6c24588b44244c8b4c24448d9b00000000896c24103beb0f8d200100008be80faf6c2458896c241c33c033db
            8bf5896c2424895c2420894424283b4424480f8d9dfcffff33c08944241485c90f8ea60000008b5424688b7c24408beb8d34
            968b54246403dfeb0a8da424000000008d4900b803000000803c03008b442414745e8b44243c0fb67c2f020fb64c06028d04
            113bf87f792bca3bf97c738b44243c0fb64c06018b4424400fb67c28018d04113bf87f5a2bca3bf97c548b44243c0fb63b0f
            b604068d0c103bf97f422bc23bf87c3c8b4424148b7c24408b4c24444083c50483c30483c604894424143bc17c818b5c2420
            8b7424240374244c8b44242840035c245089742424e924ffffff8b7c24108b6c241c8b44244c8b5c24608b4c24444703e889
            7c2410896c241c3bfb0f8cf3feffff8b7c24688b6c24584f897c24683b7c24540f8dc5feffff8b4424345fc700ffffffff8b
            4424345e5dc700ffffffffb85ff0ffff5b83c420c3,4c894c24204c89442418488954241048894c24085355565741544
            155415641574883ec188b8424c80000004d8bd94d8bd0488bda83f8010f85b3010000448b8c24a800000044890c24443b8c2
            4b80000000f8d66010000448bac24900000008b9424c0000000448b8424b00000008bbc2480000000448b9424a0000000418
            bcd410fafc9894c24040f1f84000000000044899424c8000000453bd00f8dfb000000468d2495000000000f1f80000000003
            3ed448bf933f6660f1f8400000000003bac24880000000f8d1701000033db85ff7e7e458bf4448bce442bf64503f7904d63c
            14d03c34180780300745a450fb65002438d040e4c63d84c035c2470410fb64b028d0411443bd07f572bca443bd17c50410fb
            64b01450fb650018d0411443bd07f3e2bca443bd17c37410fb60b450fb6108d0411443bd07f272bca443bd17c204c8b5c247
            8ffc34183c1043bdf7c8fffc54503fd03b42498000000e95effffff8b8424c8000000448b8424b00000008b4c24044c8b5c2
            478ffc04183c404898424c8000000413bc00f8c20ffffff448b0c24448b9424a000000041ffc14103cd44890c24894c24044
            43b8c24b80000000f8cd8feffff488b5c2468488b4c2460b85ff0ffffc701ffffffffc703ffffffff4883c418415f415e415
            d415c5f5e5d5bc38b8424c8000000e9860b000083f8020f858c010000448b8c24b800000041ffc944890c24443b8c24a8000
            0007cab448bac2490000000448b8424c00000008b9424b00000008bbc2480000000448b9424a0000000418bc9410fafcd418
            bc5894c2404f7d8894424080f1f400044899424c8000000443bd20f8d02010000468d2495000000000f1f80000000004533f
            6448bf933f60f1f840000000000443bb424880000000f8d56ffffff33db85ff0f8e81000000418bec448bd62bee4103ef496
            3d24903d3807a03007460440fb64a02418d042a4c63d84c035c2470410fb64b02428d0401443bc87f5d412bc8443bc97c554
            10fb64b01440fb64a01428d0401443bc87f42412bc8443bc97c3a410fb60b440fb60a428d0401443bc87f29412bc8443bc97
            c214c8b5c2478ffc34183c2043bdf7c8a41ffc64503fd03b42498000000e955ffffff8b8424c80000008b9424b00000008b4
            c24044c8b5c2478ffc04183c404898424c80000003bc20f8c19ffffff448b0c24448b9424a0000000034c240841ffc9894c2
            40444890c24443b8c24a80000000f8dd0feffffe933feffff83f8030f85c4010000448b8c24b800000041ffc944898c24c80
            00000443b8c24a80000000f8c0efeffff8b842490000000448b9c24b0000000448b8424c00000008bbc248000000041ffcb4
            18bc98bd044895c24080fafc8f7da890c24895424048b9424a0000000448b542404458beb443bda0f8c13010000468d249d0
            000000066660f1f84000000000033ed448bf933f6660f1f8400000000003bac24880000000f8d0801000033db85ff0f8e960
            00000488b4c2478458bf4448bd6442bf64503f70f1f8400000000004963d24803d1807a03007460440fb64a02438d04164c6
            3d84c035c2470410fb64b02428d0401443bc87f63412bc8443bc97c5b410fb64b01440fb64a01428d0401443bc87f48412bc
            8443bc97c40410fb60b440fb60a428d0401443bc87f2f412bc8443bc97c27488b4c2478ffc34183c2043bdf7c8a8b8424900
            00000ffc54403f803b42498000000e942ffffff8b9424a00000008b8424900000008b0c2441ffcd4183ec04443bea0f8d11f
            fffff448b8c24c8000000448b542404448b5c240841ffc94103ca44898c24c8000000890c24443b8c24a80000000f8dc2fef
            fffe983fcffff488b4c24608b8424c8000000448929488b4c2468890133c0e981fcffff83f8040f857f010000448b8c24a80
            0000044890c24443b8c24b80000000f8d48fcffff448bac2490000000448b9424b00000008b9424c0000000448b8424a0000
            0008bbc248000000041ffca418bcd4489542408410fafc9894c2404669044899424c8000000453bd00f8cf8000000468d249
            5000000000f1f800000000033ed448bf933f6660f1f8400000000003bac24880000000f8df7fbffff33db85ff7e7e458bf44
            48bce442bf64503f7904d63c14d03c34180780300745a450fb65002438d040e4c63d84c035c2470410fb64b028d0411443bd
            07f572bca443bd17c50410fb64b01450fb650018d0411443bd07f3e2bca443bd17c37410fb60b450fb6108d0411443bd07f2
            72bca443bd17c204c8b5c2478ffc34183c1043bdf7c8fffc54503fd03b42498000000e95effffff8b8424c8000000448b842
            4a00000008b4c24044c8b5c2478ffc84183ec04898424c8000000413bc00f8d20ffffff448b0c24448b54240841ffc14103c
            d44890c24894c2404443b8c24b80000000f8cdbfeffffe9defaffff83f8050f85ab010000448b8424a000000044890424443
            b8424b00000000f8dc0faffff8b9424c0000000448bac2498000000448ba424900000008bbc2480000000448b8c24a800000
            0428d0c8500000000898c24c800000044894c2404443b8c24b80000000f8d09010000418bc4410fafc18944240833ed448bf
            833f6660f1f8400000000003bac24880000000f8d0501000033db85ff0f8e87000000448bf1448bce442bf64503f74d63c14
            d03c34180780300745d438d040e4c63d84d03da450fb65002410fb64b028d0411443bd07f5f2bca443bd17c58410fb64b014
            50fb650018d0411443bd07f462bca443bd17c3f410fb60b450fb6108d0411443bd07f2f2bca443bd17c284c8b5c24784c8b5
            42470ffc34183c1043bdf7c8c8b8c24c8000000ffc54503fc4103f5e955ffffff448b4424048b4424088b8c24c80000004c8
            b5c24784c8b54247041ffc04103c4448944240489442408443b8424b80000000f8c0effffff448b0424448b8c24a80000004
            1ffc083c10444890424898c24c8000000443b8424b00000000f8cc5feffffe946f9ffff488b4c24608b042489018b4424044
            88b4c2468890133c0e945f9ffff83f8060f85aa010000448b8c24a000000044894c2404443b8c24b00000000f8d0bf9ffff8
            b8424b8000000448b8424c0000000448ba424900000008bbc2480000000428d0c8d00000000ffc88944240c898c24c800000
            06666660f1f840000000000448be83b8424a80000000f8c02010000410fafc4418bd4f7da891424894424084533f6448bf83
            3f60f1f840000000000443bb424880000000f8df900000033db85ff0f8e870000008be9448bd62bee4103ef4963d24903d38
            07a03007460440fb64a02418d042a4c63d84c035c2470410fb64b02428d0401443bc87f64412bc8443bc97c5c410fb64b014
            40fb64a01428d0401443bc87f49412bc8443bc97c41410fb60b440fb60a428d0401443bc87f30412bc8443bc97c284c8b5c2
            478ffc34183c2043bdf7c8a8b8c24c800000041ffc64503fc03b42498000000e94fffffff8b4424088b8c24c80000004c8b5
            c247803042441ffcd89442408443bac24a80000000f8d17ffffff448b4c24048b44240c41ffc183c10444894c2404898c24c
            8000000443b8c24b00000000f8ccefeffffe991f7ffff488b4c24608b4424048901488b4c246833c0448929e992f7ffff83f
            8070f858d010000448b8c24b000000041ffc944894c2404443b8c24a00000000f8c55f7ffff8b8424b8000000448b8424c00
            00000448ba424900000008bbc2480000000428d0c8d00000000ffc8890424898c24c8000000660f1f440000448be83b8424a
            80000000f8c02010000410fafc4418bd4f7da8954240c8944240833ed448bf833f60f1f8400000000003bac24880000000f8
            d4affffff33db85ff0f8e89000000448bf1448bd6442bf64503f74963d24903d3807a03007460440fb64a02438d04164c63d
            84c035c2470410fb64b02428d0401443bc87f63412bc8443bc97c5b410fb64b01440fb64a01428d0401443bc87f48412bc84
            43bc97c40410fb60b440fb60a428d0401443bc87f2f412bc8443bc97c274c8b5c2478ffc34183c2043bdf7c8a8b8c24c8000
            000ffc54503fc03b42498000000e94fffffff8b4424088b8c24c80000004c8b5c24780344240c41ffcd89442408443bac24a
            80000000f8d17ffffff448b4c24048b042441ffc983e90444894c2404898c24c8000000443b8c24a00000000f8dcefeffffe
            9e1f5ffff83f8080f85ddf5ffff448b8424b000000041ffc84489442404443b8424a00000000f8cbff5ffff8b9424c000000
            0448bac2498000000448ba424900000008bbc2480000000448b8c24a8000000428d0c8500000000898c24c800000044890c2
            4443b8c24b80000000f8d08010000418bc4410fafc18944240833ed448bf833f6660f1f8400000000003bac24880000000f8
            d0501000033db85ff0f8e87000000448bf1448bce442bf64503f74d63c14d03c34180780300745d438d040e4c63d84d03da4
            50fb65002410fb64b028d0411443bd07f5f2bca443bd17c58410fb64b01450fb650018d0411443bd07f462bca443bd17c3f4
            10fb603450fb6108d0c10443bd17f2f2bc2443bd07c284c8b5c24784c8b542470ffc34183c1043bdf7c8c8b8c24c8000000f
            fc54503fc4103f5e955ffffff448b04248b4424088b8c24c80000004c8b5c24784c8b54247041ffc04103c44489042489442
            408443b8424b80000000f8c10ffffff448b442404448b8c24a800000041ffc883e9044489442404898c24c8000000443b842
            4a00000000f8dc6feffffe946f4ffff8b442404488b4c246089018b0424488b4c2468890133c0e945f4ffff
            )&quot;
        if ( A_PtrSize == 8 ) ; x64, after comma
            MCode_ImageSearch := SubStr(MCode_ImageSearch,InStr(MCode_ImageSearch,&quot;,&quot;)+1)
        else ; x86, before comma
            MCode_ImageSearch := SubStr(MCode_ImageSearch,1,InStr(MCode_ImageSearch,&quot;,&quot;)-1)
        VarSetCapacity(_ImageSearch, LEN := StrLen(MCode_ImageSearch)//2, 0)
        Loop, %LEN%
            NumPut(&quot;0x&quot; . SubStr(MCode_ImageSearch,(2*A_Index)-1,2), _ImageSearch, A_Index-1, &quot;uchar&quot;)
        MCode_ImageSearch := &quot;&quot;
        DllCall(&quot;VirtualProtect&quot;, Ptr,&amp;_ImageSearch, Ptr,VarSetCapacity(_ImageSearch), &quot;uint&quot;,0x40, PtrA,0)
    }

    ; Abort if an initial coordinates is located before a final coordinate
    If ( sx2 &lt; sx1 )
        return -3001
    If ( sy2 &lt; sy1 )
        return -3002

    ; Check the search box. &quot;sx2,sy2&quot; will be the last pixel evaluated
    ; as possibly matching with the needle&#039;s first pixel. So, we must
    ; avoid going beyond this maximum final coordinate.
    If ( sx2 &gt; (hWidth-nWidth+1) )
        return -3003
    If ( sy2 &gt; (hHeight-nHeight+1) )
        return -3004

    ; Abort if the width or height of the search box is 0
    If ( sx2-sx1 == 0 )
        return -3005
    If ( sy2-sy1 == 0 )
        return -3006

    ; The DllCall parameters are the same for easier C code modification,
    ; even though they aren&#039;t all used on the _ImageSearch version
    x := 0, y := 0
    , E := DllCall( &amp;_ImageSearch, &quot;int*&quot;,x, &quot;int*&quot;,y, Ptr,hScan, Ptr,nScan, &quot;int&quot;,nWidth, &quot;int&quot;,nHeight
    , &quot;int&quot;,hStride, &quot;int&quot;,nStride, &quot;int&quot;,sx1, &quot;int&quot;,sy1, &quot;int&quot;,sx2, &quot;int&quot;,sy2, &quot;int&quot;,Variation
    , &quot;int&quot;,sd, &quot;cdecl int&quot;)
    Return ( E == &quot;&quot; ? -3007 : E )
}





Gdip_Startup()
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	if !DllCall(&quot;GetModuleHandle&quot;, &quot;str&quot;, &quot;gdiplus&quot;, Ptr)
		DllCall(&quot;LoadLibrary&quot;, &quot;str&quot;, &quot;gdiplus&quot;)
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
	DllCall(&quot;gdiplus\GdiplusStartup&quot;, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, pToken, Ptr, &amp;si, Ptr, 0)
	return pToken
}

Gdip_Shutdown(pToken)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	DllCall(&quot;gdiplus\GdiplusShutdown&quot;, Ptr, pToken)
	if hModule := DllCall(&quot;GetModuleHandle&quot;, &quot;str&quot;, &quot;gdiplus&quot;, Ptr)
		DllCall(&quot;FreeLibrary&quot;, Ptr, hModule)
	return 0
}

Gdip_CreateBitmapFromFile(sFile, IconNumber=1, IconSize=&quot;&quot;)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	, PtrA := A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;
	
	SplitPath, sFile,,, ext
	if ext in exe,dll
	{
		Sizes := IconSize ? IconSize : 256 &quot;|&quot; 128 &quot;|&quot; 64 &quot;|&quot; 48 &quot;|&quot; 32 &quot;|&quot; 16
		BufSize := 16 + (2*(A_PtrSize ? A_PtrSize : 4))
		
		VarSetCapacity(buf, BufSize, 0)
		Loop, Parse, Sizes, |
		{
			DllCall(&quot;PrivateExtractIcons&quot;, &quot;str&quot;, sFile, &quot;int&quot;, IconNumber-1, &quot;int&quot;, A_LoopField, &quot;int&quot;, A_LoopField, PtrA, hIcon, PtrA, 0, &quot;uint&quot;, 1, &quot;uint&quot;, 0)
			
			if !hIcon
				continue

			if !DllCall(&quot;GetIconInfo&quot;, Ptr, hIcon, Ptr, &amp;buf)
			{
				DestroyIcon(hIcon)
				continue
			}
			
			hbmMask  := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4))
			hbmColor := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4) + (A_PtrSize ? A_PtrSize : 4))
			if !(hbmColor &amp;&amp; DllCall(&quot;GetObject&quot;, Ptr, hbmColor, &quot;int&quot;, BufSize, Ptr, &amp;buf))
			{
				DestroyIcon(hIcon)
				continue
			}
			break
		}
		if !hIcon
			return -1

		Width := NumGet(buf, 4, &quot;int&quot;), Height := NumGet(buf, 8, &quot;int&quot;)
		hbm := CreateDIBSection(Width, -Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
		if !DllCall(&quot;DrawIconEx&quot;, Ptr, hdc, &quot;int&quot;, 0, &quot;int&quot;, 0, Ptr, hIcon, &quot;uint&quot;, Width, &quot;uint&quot;, Height, &quot;uint&quot;, 0, Ptr, 0, &quot;uint&quot;, 3)
		{
			DestroyIcon(hIcon)
			return -2
		}
		
		VarSetCapacity(dib, 104)
		DllCall(&quot;GetObject&quot;, Ptr, hbm, &quot;int&quot;, A_PtrSize = 8 ? 104 : 84, Ptr, &amp;dib) ; sizeof(DIBSECTION) = 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize
		Stride := NumGet(dib, 12, &quot;Int&quot;), Bits := NumGet(dib, 20 + (A_PtrSize = 8 ? 4 : 0)) ; padding
		DllCall(&quot;gdiplus\GdipCreateBitmapFromScan0&quot;, &quot;int&quot;, Width, &quot;int&quot;, Height, &quot;int&quot;, Stride, &quot;int&quot;, 0x26200A, Ptr, Bits, PtrA, pBitmapOld)
		pBitmap := Gdip_CreateBitmap(Width, Height)
		G := Gdip_GraphicsFromImage(pBitmap)
		, Gdip_DrawImage(G, pBitmapOld, 0, 0, Width, Height, 0, 0, Width, Height)
		SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
		Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmapOld)
		DestroyIcon(hIcon)
	}
	else
	{
		if (!A_IsUnicode)
		{
			VarSetCapacity(wFile, 1024)
			DllCall(&quot;kernel32\MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;sFile, &quot;int&quot;, -1, Ptr, &amp;wFile, &quot;int&quot;, 512)
			DllCall(&quot;gdiplus\GdipCreateBitmapFromFile&quot;, Ptr, &amp;wFile, PtrA, pBitmap)
		}
		else
			DllCall(&quot;gdiplus\GdipCreateBitmapFromFile&quot;, Ptr, &amp;sFile, PtrA, pBitmap)
	}
	
	return pBitmap
}

DestroyIcon(hIcon)
{
	return DllCall(&quot;DestroyIcon&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hIcon)
}

CreateDIBSection(w, h, hdc=&quot;&quot;, bpp=32, ByRef ppvBits=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)
	
	NumPut(w, bi, 4, &quot;uint&quot;)
	, NumPut(h, bi, 8, &quot;uint&quot;)
	, NumPut(40, bi, 0, &quot;uint&quot;)
	, NumPut(1, bi, 12, &quot;ushort&quot;)
	, NumPut(0, bi, 16, &quot;uInt&quot;)
	, NumPut(bpp, bi, 14, &quot;ushort&quot;)
	
	hbm := DllCall(&quot;CreateDIBSection&quot;
					, Ptr, hdc2
					, Ptr, &amp;bi
					, &quot;uint&quot;, 0
					, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, ppvBits
					, Ptr, 0
					, &quot;uint&quot;, 0, Ptr)

	if !hdc
		ReleaseDC(hdc2)
	return hbm
}

GetDC(hwnd=0)
{
	return DllCall(&quot;GetDC&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hwnd)
}

Gdip_CreateBitmap(Width, Height, Format=0x26200A)
{
    DllCall(&quot;gdiplus\GdipCreateBitmapFromScan0&quot;, &quot;int&quot;, Width, &quot;int&quot;, Height, &quot;int&quot;, 0, &quot;int&quot;, Format, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, 0, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, pBitmap)
    Return pBitmap
}

Gdip_GraphicsFromImage(pBitmap)
{
	DllCall(&quot;gdiplus\GdipGetImageGraphicsContext&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pGraphics)
	return pGraphics
}

CreateCompatibleDC(hdc=0)
{
   return DllCall(&quot;CreateCompatibleDC&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hdc)
}

SelectObject(hdc, hgdiobj)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;SelectObject&quot;, Ptr, hdc, Ptr, hgdiobj)
}

Gdip_DrawImage(pGraphics, pBitmap, dx=&quot;&quot;, dy=&quot;&quot;, dw=&quot;&quot;, dh=&quot;&quot;, sx=&quot;&quot;, sy=&quot;&quot;, sw=&quot;&quot;, sh=&quot;&quot;, Matrix=1)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	if (Matrix&amp;1 = &quot;&quot;)
		ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
	else if (Matrix != 1)
		ImageAttr := Gdip_SetImageAttributesColorMatrix(&quot;1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|&quot; Matrix &quot;|0|0|0|0|0|1&quot;)

	if (sx = &quot;&quot; &amp;&amp; sy = &quot;&quot; &amp;&amp; sw = &quot;&quot; &amp;&amp; sh = &quot;&quot;)
	{
		if (dx = &quot;&quot; &amp;&amp; dy = &quot;&quot; &amp;&amp; dw = &quot;&quot; &amp;&amp; dh = &quot;&quot;)
		{
			sx := dx := 0, sy := dy := 0
			sw := dw := Gdip_GetImageWidth(pBitmap)
			sh := dh := Gdip_GetImageHeight(pBitmap)
		}
		else
		{
			sx := sy := 0
			sw := Gdip_GetImageWidth(pBitmap)
			sh := Gdip_GetImageHeight(pBitmap)
		}
	}

	E := DllCall(&quot;gdiplus\GdipDrawImageRectRect&quot;
				, Ptr, pGraphics
				, Ptr, pBitmap
				, &quot;float&quot;, dx
				, &quot;float&quot;, dy
				, &quot;float&quot;, dw
				, &quot;float&quot;, dh
				, &quot;float&quot;, sx
				, &quot;float&quot;, sy
				, &quot;float&quot;, sw
				, &quot;float&quot;, sh
				, &quot;int&quot;, 2
				, Ptr, ImageAttr
				, Ptr, 0
				, Ptr, 0)
	if ImageAttr
		Gdip_DisposeImageAttributes(ImageAttr)
	return E
}

Gdip_SetImageAttributesColorMatrix(Matrix)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	VarSetCapacity(ColourMatrix, 100, 0)
	Matrix := RegExReplace(RegExReplace(Matrix, &quot;^[^\d-\.]+([\d\.])&quot;, &quot;$1&quot;, &quot;&quot;, 1), &quot;[^\d-\.]+&quot;, &quot;|&quot;)
	StringSplit, Matrix, Matrix, |
	Loop, 25
	{
		Matrix := (Matrix%A_Index% != &quot;&quot;) ? Matrix%A_Index% : Mod(A_Index-1, 6) ? 0 : 1
		NumPut(Matrix, ColourMatrix, (A_Index-1)*4, &quot;float&quot;)
	}
	DllCall(&quot;gdiplus\GdipCreateImageAttributes&quot;, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, ImageAttr)
	DllCall(&quot;gdiplus\GdipSetImageAttributesColorMatrix&quot;, Ptr, ImageAttr, &quot;int&quot;, 1, &quot;int&quot;, 1, Ptr, &amp;ColourMatrix, Ptr, 0, &quot;int&quot;, 0)
	return ImageAttr
}

Gdip_GetImageWidth(pBitmap)
{
   DllCall(&quot;gdiplus\GdipGetImageWidth&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, &quot;uint*&quot;, Width)
   return Width
}

Gdip_GetImageHeight(pBitmap)
{
   DllCall(&quot;gdiplus\GdipGetImageHeight&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, &quot;uint*&quot;, Height)
   return Height
}

DeleteObject(hObject)
{
   return DllCall(&quot;DeleteObject&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hObject)
}

DeleteDC(hdc)
{
   return DllCall(&quot;DeleteDC&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hdc)
}

Gdip_DeleteGraphics(pGraphics)
{
   return DllCall(&quot;gdiplus\GdipDeleteGraphics&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics)
}

Gdip_DisposeImage(pBitmap)
{
   return DllCall(&quot;gdiplus\GdipDisposeImage&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap)
}

Gdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	DllCall(&quot;gdiplus\GdipGetImageWidth&quot;, Ptr, pBitmap, &quot;uint*&quot;, Width)
	DllCall(&quot;gdiplus\GdipGetImageHeight&quot;, Ptr, pBitmap, &quot;uint*&quot;, Height)
}

Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode = 3, PixelFormat = 0x26200a)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	CreateRect(Rect, x, y, w, h)
	VarSetCapacity(BitmapData, 16+2*(A_PtrSize ? A_PtrSize : 4), 0)
	E := DllCall(&quot;Gdiplus\GdipBitmapLockBits&quot;, Ptr, pBitmap, Ptr, &amp;Rect, &quot;uint&quot;, LockMode, &quot;int&quot;, PixelFormat, Ptr, &amp;BitmapData)
	Stride := NumGet(BitmapData, 8, &quot;Int&quot;)
	Scan0 := NumGet(BitmapData, 16, Ptr)
	return E
}

Gdip_UnlockBits(pBitmap, ByRef BitmapData)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;Gdiplus\GdipBitmapUnlockBits&quot;, Ptr, pBitmap, Ptr, &amp;BitmapData)
}

CreateRect(ByRef Rect, x, y, w, h)
{
	VarSetCapacity(Rect, 16)
	NumPut(x, Rect, 0, &quot;uint&quot;), NumPut(y, Rect, 4, &quot;uint&quot;), NumPut(w, Rect, 8, &quot;uint&quot;), NumPut(h, Rect, 12, &quot;uint&quot;)
}

Gdip_CloneBitmapArea(pBitmap, x, y, w, h, Format=0x26200A)
{
	DllCall(&quot;gdiplus\GdipCloneBitmapArea&quot;
					, &quot;float&quot;, x
					, &quot;float&quot;, y
					, &quot;float&quot;, w
					, &quot;float&quot;, h
					, &quot;int&quot;, Format
					, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap
					, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pBitmapDest)
	return pBitmapDest
}

Gdip_FromARGB(ARGB, ByRef A, ByRef R, ByRef G, ByRef B)
{
	A := (0xff000000 &amp; ARGB) &gt;&gt; 24
	R := (0x00ff0000 &amp; ARGB) &gt;&gt; 16
	G := (0x0000ff00 &amp; ARGB) &gt;&gt; 8
	B := 0x000000ff &amp; ARGB
}

ReleaseDC(hdc, hwnd=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;ReleaseDC&quot;, Ptr, hwnd, Ptr, hdc)
}

Gdip_DisposeImageAttributes(ImageAttr)
{
	return DllCall(&quot;gdiplus\GdipDisposeImageAttributes&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, ImageAttr)
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Fri, 09 Oct 2020 14:16:35 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142578#p142578</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142572#p142572</link>
			<description><![CDATA[<p>Вот так примерно может выглядеть через directx + gdip search<br />Для поиска использовал эту библиотеку:<br /><a href="https://github.com/MasterFocus/AutoHotkey/blob/master/Functions/Gdip_ImageSearch/Gdip_ImageSearch.ahk">https://github.com/MasterFocus/AutoHotk … Search.ahk</a><br />Хотя возможно эта будет быстрее:<br /><a href="https://github.com/MasterFocus/AutoHotkey/tree/912011380caf37a690ff911d9ded388f4ada2f4e/Functions/GDI%2B%20ImageSearch">https://github.com/MasterFocus/AutoHotk … mageSearch</a><br />Во всяком случае пару лет назад я так считал:<br /><a href="http://forum.script-coding.com/viewtopic.php?pid=120347#p120347">http://forum.script-coding.com/viewtopi … 47#p120347</a><br />Захват экрана удобно делать через IDXGIOutputDuplication апи, так как захват происходит только при изменении десктопа.<br />Например, если смотреть видео на ютубе со скоростью 25 кадров в секунду, то и захват будет 25 кадров в секунду.<br /></p><div class="codebox"><pre><code>search := &quot;needle.bmp&quot;
x1 := 1300, y1 := 0, x2 := 1500, y2 := 200

f11::
setbatchlines -1

pToken := Gdip_Startup()
pBitmapNeedle := Gdip_CreateBitmapFromFile(search)
Gdip_GetImageDimensions(pBitmapNeedle, nWidth, nHeight)
Gdip_LockBits(pBitmapNeedle, 0, 0, nWidth, nHeight, nStride, nScan, nBitmapData)

IDXGIFactory := CreateDXGIFactory()
if !IDXGIFactory
{
   MsgBox, 16, Error, Create IDXGIFactory failed.
   ExitApp
}
loop
{
   IDXGIFactory_EnumAdapters(IDXGIFactory, A_Index-1, IDXGIAdapter)
   loop
   {
      hr := IDXGIAdapter_EnumOutputs(IDXGIAdapter, A_Index-1, IDXGIOutput)
      if (hr = &quot;DXGI_ERROR_NOT_FOUND&quot;)
         break
      VarSetCapacity(DXGI_OUTPUT_DESC, 88+A_PtrSize, 0)
      IDXGIOutput_GetDesc(IDXGIOutput, &amp;DXGI_OUTPUT_DESC)
      hWidth := NumGet(DXGI_OUTPUT_DESC, 72, &quot;int&quot;)
      hHeight := NumGet(DXGI_OUTPUT_DESC, 76, &quot;int&quot;)
      AttachedToDesktop := NumGet(DXGI_OUTPUT_DESC, 80, &quot;int&quot;)
      if (AttachedToDesktop = 1)
         break 2         
   }
}
if (AttachedToDesktop != 1)
{
   MsgBox, 16, Error, No adapter attached to desktop
   ExitApp
}
D3D11CreateDevice(IDXGIAdapter, D3D_DRIVER_TYPE_UNKNOWN := 0, 0, 0, 0, 0, D3D11_SDK_VERSION := 7, d3d_device, 0, d3d_context)
IDXGIOutput1 := IDXGIOutput1_Query(IDXGIOutput)
IDXGIOutput1_DuplicateOutput(IDXGIOutput1, d3d_device, Duplication)
VarSetCapacity(DXGI_OUTDUPL_DESC, 36, 0)
IDXGIOutputDuplication_GetDesc(Duplication, &amp;DXGI_OUTDUPL_DESC)
DesktopImageInSystemMemory := NumGet(DXGI_OUTDUPL_DESC, 32, &quot;uint&quot;)
sleep 50   ; As I understand - need some sleep for successful connecting to IDXGIOutputDuplication interface

VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
NumPut(hWidth, D3D11_TEXTURE2D_DESC, 0, &quot;uint&quot;)   ; Width
NumPut(hHeight, D3D11_TEXTURE2D_DESC, 4, &quot;uint&quot;)   ; Height
NumPut(1, D3D11_TEXTURE2D_DESC, 8, &quot;uint&quot;)   ; MipLevels
NumPut(1, D3D11_TEXTURE2D_DESC, 12, &quot;uint&quot;)   ; ArraySize
NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, &quot;uint&quot;)   ; Format 
NumPut(1, D3D11_TEXTURE2D_DESC, 20, &quot;uint&quot;)   ; SampleDescCount
NumPut(0, D3D11_TEXTURE2D_DESC, 24, &quot;uint&quot;)   ; SampleDescQuality
NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, &quot;uint&quot;)   ; Usage
NumPut(0, D3D11_TEXTURE2D_DESC, 32, &quot;uint&quot;)   ; BindFlags
NumPut(D3D11_CPU_ACCESS_READ := 0x20000, D3D11_TEXTURE2D_DESC, 36, &quot;uint&quot;)   ; CPUAccessFlags
NumPut(0, D3D11_TEXTURE2D_DESC, 40, &quot;uint&quot;)   ; MiscFlags
ID3D11Device_CreateTexture2D(d3d_device, &amp;D3D11_TEXTURE2D_DESC, 0, staging_tex)

x2 := ( !x2 ? hWidth-nWidth+1 : x2-nWidth+1 )
y2 := ( !y2 ? hHeight-nHeight+1 : y2-nHeight+1 )

a := a_tickcount
loop 1000
{
   tooltip % A_Index
   loop
   {
      VarSetCapacity(DXGI_OUTDUPL_FRAME_INFO, 48, 0)
      AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, INFINITE := 0xFFFFFFFF, &amp;DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
      LastPresentTime := NumGet(DXGI_OUTDUPL_FRAME_INFO, 0, &quot;int64&quot;)
      if (LastPresentTime != 0)
      {
         if (DesktopImageInSystemMemory = 1)
         {
            VarSetCapacity(DXGI_MAPPED_RECT, A_PtrSize*2, 0)
            IDXGIOutputDuplication_MapDesktopSurface(Duplication, &amp;DXGI_MAPPED_RECT)
            hStride := NumGet(DXGI_MAPPED_RECT, 0, &quot;int&quot;)
            hScan := NumGet(DXGI_MAPPED_RECT, A_PtrSize, &quot;ptr&quot;)
         }
         else
         {
            tex := ID3D11Texture2D_Query(desktop_resource)
            ID3D11DeviceContext_CopyResource(d3d_context, staging_tex, tex)
            VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
            ID3D11DeviceContext_Map(d3d_context, staging_tex, 0, D3D11_MAP_READ := 1, 0, &amp;D3D11_MAPPED_SUBRESOURCE)
            hScan := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, &quot;ptr&quot;)
            hStride := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, &quot;uint&quot;)
         }

         if !Gdip_LockedBitsSearch(hStride, hScan, hWidth, hHeight, nStride, nScan, nWidth, nHeight, x, y, x1, y1, x2, y2)
            msgbox % x &quot; - &quot; y

         if (DesktopImageInSystemMemory = 1)
            IDXGIOutputDuplication_UnMapDesktopSurface(Duplication)
         else
         {
            ID3D11DeviceContext_Unmap(d3d_context, staging_tex, 0)
            ObjRelease(tex)
         }
         ObjRelease(desktop_resource)
         IDXGIOutputDuplication_ReleaseFrame(duplication)
         break
      }
      ObjRelease(desktop_resource)
      IDXGIOutputDuplication_ReleaseFrame(duplication)
   }
}
msgbox % a_tickcount - a
Gdip_UnlockBits(pBitmapNeedle, nBitmapData)
Gdip_DisposeImage(pBitmapNeedle)
Release(staging_tex)
Release(d3d_device)
Release(d3d_context)
Release(duplication)
Release(IDXGIAdapter)
Release(IDXGIOutput)
Release(IDXGIOutput1)
Release(IDXGIFactory)
ExitApp



CreateDXGIFactory()
{
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;DXGI&quot;)
      DllCall(&quot;LoadLibrary&quot;,&quot;str&quot;,&quot;DXGI&quot;)
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;D3D11&quot;)
      DllCall(&quot;LoadLibrary&quot;,&quot;str&quot;,&quot;D3D11&quot;)
   GUID(riid, &quot;{7b7166ec-21c7-44ae-b21a-c9ae321ae369}&quot;)
   hr := DllCall(&quot;DXGI\CreateDXGIFactory1&quot;, &quot;ptr&quot;, &amp;riid, &quot;ptr*&quot;, ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return ppFactory
}

IDXGIFactory_EnumAdapters(this, Adapter, ByRef ppAdapter)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), &quot;ptr&quot;, this, &quot;uint&quot;, Adapter, &quot;ptr*&quot;, ppAdapter)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

IDXGIAdapter_EnumOutputs(this, Output, ByRef ppOutput)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), &quot;ptr&quot;, this, &quot;uint&quot;, Output, &quot;ptr*&quot;, ppOutput)
   if hr or ErrorLevel
   {
      if (hr&amp;=0xFFFFFFFF) = 0x887A0002   ; DXGI_ERROR_NOT_FOUND
         return &quot;DXGI_ERROR_NOT_FOUND&quot;
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   }
}

IDXGIAdapter_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*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)
}

IDXGIOutput_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*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)
}

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

IDXGIOutputDuplication_AcquireNextFrame(this, TimeoutInMilliseconds, pFrameInfo, ByRef ppDesktopResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), &quot;ptr&quot;, this, &quot;uint&quot;, TimeoutInMilliseconds, &quot;ptr&quot;, pFrameInfo, &quot;ptr*&quot;, ppDesktopResource)
   if hr or ErrorLevel
   {
      if (hr&amp;=0xFFFFFFFF) = 0x887A0027   ; DXGI_ERROR_WAIT_TIMEOUT
         return &quot;DXGI_ERROR_WAIT_TIMEOUT&quot;
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   }
}

D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ByRef ppDevice, ByRef pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall(&quot;D3D11\D3D11CreateDevice&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;, ppDevice, &quot;ptr*&quot;, pFeatureLevel, &quot;ptr*&quot;, ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

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

IDXGIOutputDuplication_MapDesktopSurface(this, pLockedRect)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pLockedRect)
   if hr or ErrorLevel
   {
      if (hr&amp;=0xFFFFFFFF) = 0x887A0004   ; DXGI_ERROR_UNSUPPORTED
         return &quot;DXGI_ERROR_UNSUPPORTED&quot;
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   }
}

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

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

IDXGIOutput1_DuplicateOutput(this, pDevice, ByRef ppOutputDuplication)
{
   hr := DllCall(NumGet(NumGet(this+0)+22*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDevice, &quot;ptr*&quot;, ppOutputDuplication)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

IDXGIOutput1_Query(IDXGIOutput)
{ 
   hr := ComObjQuery(IDXGIOutput, &quot;{00cddea8-939b-4b83-a340-a685226666cc}&quot;)
   if !hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return hr
}

ID3D11Texture2D_Query(desktop_resource)
{ 
   hr := ComObjQuery(desktop_resource, &quot;{6f15aaf2-d208-4e89-9ab4-489535d34f9c}&quot;)
   if !hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return hr
}

ID3D11DeviceContext_CopyResource(this, pDstResource, pSrcResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+47*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDstResource, &quot;ptr&quot;, pSrcResource)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11DeviceContext_CopySubresourceRegion(this, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox)
{
   hr := DllCall(NumGet(NumGet(this+0)+46*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDstResource, &quot;uint&quot;, DstSubresource, &quot;uint&quot;, DstX, &quot;uint&quot;, DstY, &quot;uint&quot;, DstZ, &quot;ptr&quot;, pSrcResource, &quot;uint&quot;, SrcSubresource, &quot;ptr&quot;, pSrcBox)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11DeviceContext_Map(this, pResource, Subresource, MapType, MapFlags, pMappedResource)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pResource, &quot;uint&quot;, Subresource, &quot;uint&quot;, MapType, &quot;uint&quot;, MapFlags, &quot;ptr&quot;, pMappedResource)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11DeviceContext_Unmap(this, pResource, Subresource)
{
   hr := DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pResource, &quot;uint&quot;, Subresource)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

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
}










;**********************************************************************************
;
; Gdip_ImageSearch()
; by MasterFocus - 02/APRIL/2013 00:30h BRT
; Thanks to guest3456 for helping me ponder some ideas
; Requires GDIP, Gdip_SetBitmapTransColor() and Gdip_MultiLockedBitsSearch()
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition of the license EXCLUSIVELY
; for these users: tic , Rseding91 , guest3456
;
;==================================================================================
;
; This function searches for pBitmapNeedle within pBitmapHaystack
; The returned value is the number of instances found (negative = error)
;
; ++ PARAMETERS ++
;
; pBitmapHaystack and pBitmapNeedle
;   Self-explanatory bitmap pointers, are the only required parameters
;
; OutputList
;   ByRef variable to store the list of coordinates where a match was found
;
; OuterX1, OuterY1, OuterX2, OuterY2
;   Equivalent to ImageSearch&#039;s X1,Y1,X2,Y2
;   Default: 0 for all (which searches the whole haystack area)
;
; Variation
;   Just like ImageSearch, a value from 0 to 255
;   Default: 0
;
; Trans
;   Needle RGB transparent color, should be a numerical value from 0 to 0xFFFFFF
;   Default: blank (does not use transparency)
;
; SearchDirection
;   Haystack search direction
;     Vertical preference:
;       1 = top-&gt;left-&gt;right-&gt;bottom [default]
;       2 = bottom-&gt;left-&gt;right-&gt;top
;       3 = bottom-&gt;right-&gt;left-&gt;top
;       4 = top-&gt;right-&gt;left-&gt;bottom
;     Horizontal preference:
;       5 = left-&gt;top-&gt;bottom-&gt;right
;       6 = left-&gt;bottom-&gt;top-&gt;right
;       7 = right-&gt;bottom-&gt;top-&gt;left
;       8 = right-&gt;top-&gt;bottom-&gt;left
;
; Instances
;   Maximum number of instances to find when searching (0 = find all)
;   Default: 1 (stops after one match is found)
;
; LineDelim and CoordDelim
;   Outer and inner delimiters for the list of coordinates (OutputList)
;   Defaults: &quot;`n&quot; and &quot;,&quot;
;
; ++ RETURN VALUES ++
;
; -1001 ==&gt; invalid haystack and/or needle bitmap pointer
; -1002 ==&gt; invalid variation value
; -1003 ==&gt; X1 and Y1 cannot be negative
; -1004 ==&gt; unable to lock haystack bitmap bits
; -1005 ==&gt; unable to lock needle bitmap bits
; any non-negative value ==&gt; the number of instances found
;
;==================================================================================
;
;**********************************************************************************

Gdip_ImageSearch(pBitmapHaystack,pBitmapNeedle,ByRef OutputList=&quot;&quot;,OuterX1=0,OuterY1=0,OuterX2=0,OuterY2=0,Variation=0,Trans=&quot;&quot;,SearchDirection=1,Instances=1,LineDelim=&quot;`n&quot;,CoordDelim=&quot;,&quot;) {
    ; Some validations that can be done before proceeding any further
    If !( pBitmapHaystack &amp;&amp; pBitmapNeedle )
        Return -1001
    If Variation not between 0 and 255
        return -1002
    If ( ( OuterX1 &lt; 0 ) || ( OuterY1 &lt; 0 ) )
        return -1003
    If SearchDirection not between 1 and 8
        SearchDirection := 1
    If ( Instances &lt; 0 )
        Instances := 0

    ; Getting the dimensions and locking the bits [haystack]
    Gdip_GetImageDimensions(pBitmapHaystack,hWidth,hHeight)
    ; Last parameter being 1 says the LockMode flag is &quot;READ only&quot;
    If Gdip_LockBits(pBitmapHaystack,0,0,hWidth,hHeight,hStride,hScan,hBitmapData,1)
    OR !(hWidth := NumGet(hBitmapData,0,&quot;UInt&quot;))
    OR !(hHeight := NumGet(hBitmapData,4,&quot;UInt&quot;))
        Return -1004

    ; Careful! From this point on, we must do the following before returning:
    ; - unlock haystack bits

    ; Getting the dimensions and locking the bits [needle]
    Gdip_GetImageDimensions(pBitmapNeedle,nWidth,nHeight)
    ; If Trans is correctly specified, create a backup of the original needle bitmap
    ; and modify the current one, setting the desired color as transparent.
    ; Also, since a copy is created, we must remember to dispose the new bitmap later.
    ; This whole thing has to be done before locking the bits.
    If Trans between 0 and 0xFFFFFF
    {
        pOriginalBmpNeedle := pBitmapNeedle
        pBitmapNeedle := Gdip_CloneBitmapArea(pOriginalBmpNeedle,0,0,nWidth,nHeight)
        Gdip_SetBitmapTransColor(pBitmapNeedle,Trans)
        DumpCurrentNeedle := true
    }

    ; Careful! From this point on, we must do the following before returning:
    ; - unlock haystack bits
    ; - dispose current needle bitmap (if necessary)

    If Gdip_LockBits(pBitmapNeedle,0,0,nWidth,nHeight,nStride,nScan,nBitmapData)
    OR !(nWidth := NumGet(nBitmapData,0,&quot;UInt&quot;))
    OR !(nHeight := NumGet(nBitmapData,4,&quot;UInt&quot;))
    {
        If ( DumpCurrentNeedle )
            Gdip_DisposeImage(pBitmapNeedle)
        Gdip_UnlockBits(pBitmapHaystack,hBitmapData)
        Return -1005
    }
    
    ; Careful! From this point on, we must do the following before returning:
    ; - unlock haystack bits
    ; - unlock needle bits
    ; - dispose current needle bitmap (if necessary)

    ; Adjust the search box. &quot;OuterX2,OuterY2&quot; will be the last pixel evaluated
    ; as possibly matching with the needle&#039;s first pixel. So, we must avoid going
    ; beyond this maximum final coordinate.
    OuterX2 := ( !OuterX2 ? hWidth-nWidth+1 : OuterX2-nWidth+1 )
    OuterY2 := ( !OuterY2 ? hHeight-nHeight+1 : OuterY2-nHeight+1 )

    OutputCount := Gdip_MultiLockedBitsSearch(hStride,hScan,hWidth,hHeight
    ,nStride,nScan,nWidth,nHeight,OutputList,OuterX1,OuterY1,OuterX2,OuterY2
    ,Variation,SearchDirection,Instances,LineDelim,CoordDelim)

    Gdip_UnlockBits(pBitmapHaystack,hBitmapData)
    Gdip_UnlockBits(pBitmapNeedle,nBitmapData)
    If ( DumpCurrentNeedle )
        Gdip_DisposeImage(pBitmapNeedle)

    Return OutputCount
}

;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

;**********************************************************************************
;
; Gdip_SetBitmapTransColor()
; by MasterFocus - 02/APRIL/2013 00:30h BRT
; Requires GDIP
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition of the license EXCLUSIVELY
; for these users: tic , Rseding91 , guest3456
;
;**********************************************************************************

;==================================================================================
;
; This function modifies the Alpha component for all pixels of a certain color to 0
; The returned value is 0 in case of success, or a negative number otherwise
;
; ++ PARAMETERS ++
;
; pBitmap
;   A valid pointer to the bitmap that will be modified
;
; TransColor
;   The color to become transparent
;   Should range from 0 (black) to 0xFFFFFF (white)
;
; ++ RETURN VALUES ++
;
; -2001 ==&gt; invalid bitmap pointer
; -2002 ==&gt; invalid TransColor
; -2003 ==&gt; unable to retrieve bitmap positive dimensions
; -2004 ==&gt; unable to lock bitmap bits
; -2005 ==&gt; DllCall failed (see ErrorLevel)
; any non-negative value ==&gt; the number of pixels modified by this function
;
;==================================================================================

Gdip_SetBitmapTransColor(pBitmap,TransColor) {
    static _SetBmpTrans, Ptr, PtrA
    if !( _SetBmpTrans ) {
        Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
        PtrA := Ptr . &quot;*&quot;
        MCode_SetBmpTrans := &quot;
            (LTrim Join
            8b44240c558b6c241cc745000000000085c07e77538b5c2410568b74242033c9578b7c2414894c24288da424000000
            0085db7e458bc18d1439b9020000008bff8a0c113a4e0275178a4c38013a4e01750e8a0a3a0e7508c644380300ff450083c0
            0483c204b9020000004b75d38b4c24288b44241c8b5c2418034c242048894c24288944241c75a85f5e5b33c05dc3,405
            34c8b5424388bda41c702000000004585c07e6448897c2410458bd84c8b4424304963f94c8d49010f1f800000000085db7e3
            8498bc1488bd3660f1f440000410fb648023848017519410fb6480138087510410fb6083848ff7507c640020041ff024883c
            00448ffca75d44c03cf49ffcb75bc488b7c241033c05bc3
            )&quot;
        if ( A_PtrSize == 8 ) ; x64, after comma
            MCode_SetBmpTrans := SubStr(MCode_SetBmpTrans,InStr(MCode_SetBmpTrans,&quot;,&quot;)+1)
        else ; x86, before comma
            MCode_SetBmpTrans := SubStr(MCode_SetBmpTrans,1,InStr(MCode_SetBmpTrans,&quot;,&quot;)-1)
        VarSetCapacity(_SetBmpTrans, LEN := StrLen(MCode_SetBmpTrans)//2, 0)
        Loop, %LEN%
            NumPut(&quot;0x&quot; . SubStr(MCode_SetBmpTrans,(2*A_Index)-1,2), _SetBmpTrans, A_Index-1, &quot;uchar&quot;)
        MCode_SetBmpTrans := &quot;&quot;
        DllCall(&quot;VirtualProtect&quot;, Ptr,&amp;_SetBmpTrans, Ptr,VarSetCapacity(_SetBmpTrans), &quot;uint&quot;,0x40, PtrA,0)
    }
    If !pBitmap
        Return -2001
    If TransColor not between 0 and 0xFFFFFF
        Return -2002
    Gdip_GetImageDimensions(pBitmap,W,H)
    If !(W &amp;&amp; H)
        Return -2003
    If Gdip_LockBits(pBitmap,0,0,W,H,Stride,Scan,BitmapData)
        Return -2004
    ; The following code should be slower than using the MCode approach,
    ; but will the kept here for now, just for reference.
    /*
    Count := 0
    Loop, %H% {
        Y := A_Index-1
        Loop, %W% {
            X := A_Index-1
            CurrentColor := Gdip_GetLockBitPixel(Scan,X,Y,Stride)
            If ( (CurrentColor &amp; 0xFFFFFF) == TransColor )
                Gdip_SetLockBitPixel(TransColor,Scan,X,Y,Stride), Count++
        }
    }
    */
    ; Thanks guest3456 for helping with the initial solution involving NumPut
    Gdip_FromARGB(TransColor,A,R,G,B), VarSetCapacity(TransColor,0), VarSetCapacity(TransColor,3,255)
    NumPut(B,TransColor,0,&quot;UChar&quot;), NumPut(G,TransColor,1,&quot;UChar&quot;), NumPut(R,TransColor,2,&quot;UChar&quot;)
    MCount := 0
    E := DllCall(&amp;_SetBmpTrans, Ptr,Scan, &quot;int&quot;,W, &quot;int&quot;,H, &quot;int&quot;,Stride, Ptr,&amp;TransColor, &quot;int*&quot;,MCount, &quot;cdecl int&quot;)
    Gdip_UnlockBits(pBitmap,BitmapData)
    If ( E != 0 ) {
        ErrorLevel := E
        Return -2005
    }
    Return MCount
}

;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

;**********************************************************************************
;
; Gdip_MultiLockedBitsSearch()
; by MasterFocus - 24/MARCH/2013 06:20h BRT
; Requires GDIP and Gdip_LockedBitsSearch()
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition of the license EXCLUSIVELY
; for these users: tic , Rseding91 , guest3456
;
;**********************************************************************************

;==================================================================================
;
; This function returns the number of instances found
; The 8 first parameters are the same as in Gdip_LockedBitsSearch()
; The other 10 parameters are the same as in Gdip_ImageSearch()
; Note: the default for the Intances parameter here is 0 (find all matches)
;
;==================================================================================

Gdip_MultiLockedBitsSearch(hStride,hScan,hWidth,hHeight,nStride,nScan,nWidth,nHeight
,ByRef OutputList=&quot;&quot;,OuterX1=0,OuterY1=0,OuterX2=0,OuterY2=0,Variation=0
,SearchDirection=1,Instances=0,LineDelim=&quot;`n&quot;,CoordDelim=&quot;,&quot;)
{
    OutputList := &quot;&quot;
    OutputCount := !Instances
    InnerX1 := OuterX1 , InnerY1 := OuterY1
    InnerX2 := OuterX2 , InnerY2 := OuterY2

    ; The following part is a rather ugly but working hack that I
    ; came up with to adjust the variables and their increments
    ; according to the specified Haystack Search Direction
    /*
    Mod(SD,4) = 0 --&gt; iX = 2 , stepX = +0 , iY = 1 , stepY = +1
    Mod(SD,4) = 1 --&gt; iX = 1 , stepX = +1 , iY = 1 , stepY = +1
    Mod(SD,4) = 2 --&gt; iX = 1 , stepX = +1 , iY = 2 , stepY = +0
    Mod(SD,4) = 3 --&gt; iX = 2 , stepX = +0 , iY = 2 , stepY = +0
    SD &lt;= 4   ------&gt; Vertical preference
    SD &gt; 4    ------&gt; Horizontal preference
    */
    ; Set the index and the step (for both X and Y) to +1
    iX := 1, stepX := 1, iY := 1, stepY := 1
    ; Adjust Y variables if SD is 2, 3, 6 or 7
    Modulo := Mod(SearchDirection,4)
    If ( Modulo &gt; 1 )
        iY := 2, stepY := 0
    ; adjust X variables if SD is 3, 4, 7 or 8
    If !Mod(Modulo,3)
        iX := 2, stepX := 0
    ; Set default Preference to vertical and Nonpreference to horizontal
    P := &quot;Y&quot;, N := &quot;X&quot;
    ; adjust Preference and Nonpreference if SD is 5, 6, 7 or 8
    If ( SearchDirection &gt; 4 )
        P := &quot;X&quot;, N := &quot;Y&quot;
    ; Set the Preference Index and the Nonpreference Index
    iP := i%P%, iN := i%N%

    While (!(OutputCount == Instances) &amp;&amp; (0 == Gdip_LockedBitsSearch(hStride,hScan,hWidth,hHeight,nStride
    ,nScan,nWidth,nHeight,FoundX,FoundY,OuterX1,OuterY1,OuterX2,OuterY2,Variation,SearchDirection)))
    {
        OutputCount++
        OutputList .= LineDelim FoundX CoordDelim FoundY
        Outer%P%%iP% := Found%P%+step%P%
        Inner%N%%iN% := Found%N%+step%N%
        Inner%P%1 := Found%P%
        Inner%P%2 := Found%P%+1
        While (!(OutputCount == Instances) &amp;&amp; (0 == Gdip_LockedBitsSearch(hStride,hScan,hWidth,hHeight,nStride
        ,nScan,nWidth,nHeight,FoundX,FoundY,InnerX1,InnerY1,InnerX2,InnerY2,Variation,SearchDirection)))
        {
            OutputCount++
            OutputList .= LineDelim FoundX CoordDelim FoundY
            Inner%N%%iN% := Found%N%+step%N%
        }
    }
    OutputList := SubStr(OutputList,1+StrLen(LineDelim))
    OutputCount -= !Instances
    Return OutputCount
}

;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

;**********************************************************************************
;
; Gdip_LockedBitsSearch()
; by MasterFocus - 24/MARCH/2013 06:20h BRT
; Mostly adapted from previous work by tic and Rseding91
;
; Requires GDIP
; http://www.autohotkey.com/board/topic/71100-gdip-imagesearch/
;
; Licensed under CC BY-SA 3.0 -&gt; http://creativecommons.org/licenses/by-sa/3.0/
; I waive compliance with the &quot;Share Alike&quot; condition of the license EXCLUSIVELY
; for these users: tic , Rseding91 , guest3456
;
;**********************************************************************************

;==================================================================================
;
; This function searches for a single match of nScan within hScan
;
; ++ PARAMETERS ++
;
; hStride, hScan, hWidth and hHeight
;   Haystack stuff, extracted from a BitmapData, extracted from a Bitmap
;
; nStride, nScan, nWidth and nHeight
;   Needle stuff, extracted from a BitmapData, extracted from a Bitmap
;
; x and y
;   ByRef variables to store the X and Y coordinates of the image if it&#039;s found
;   Default: &quot;&quot; for both
;
; sx1, sy1, sx2 and sy2
;   These can be used to crop the search area within the haystack
;   Default: &quot;&quot; for all (does not crop)
;
; Variation
;   Same as the builtin ImageSearch command
;   Default: 0
;
; sd
;   Haystack search direction
;     Vertical preference:
;       1 = top-&gt;left-&gt;right-&gt;bottom [default]
;       2 = bottom-&gt;left-&gt;right-&gt;top
;       3 = bottom-&gt;right-&gt;left-&gt;top
;       4 = top-&gt;right-&gt;left-&gt;bottom
;     Horizontal preference:
;       5 = left-&gt;top-&gt;bottom-&gt;right
;       6 = left-&gt;bottom-&gt;top-&gt;right
;       7 = right-&gt;bottom-&gt;top-&gt;left
;       8 = right-&gt;top-&gt;bottom-&gt;left
;   This value is passed to the internal MCoded function
;
; ++ RETURN VALUES ++
;
; -3001 to -3006 ==&gt; search area incorrectly defined
; -3007 ==&gt; DllCall returned blank
; 0 ==&gt; DllCall succeeded and a match was found
; -4001 ==&gt; DllCall succeeded but a match was not found
; anything else ==&gt; the error value returned by the unsuccessful DllCall
;
;==================================================================================

Gdip_LockedBitsSearch(hStride,hScan,hWidth,hHeight,nStride,nScan,nWidth,nHeight
,ByRef x=&quot;&quot;,ByRef y=&quot;&quot;,sx1=0,sy1=0,sx2=0,sy2=0,Variation=0,sd=1)
{
    static _ImageSearch, Ptr, PtrA

    ; Initialize all MCode stuff, if necessary
    if !( _ImageSearch ) {
        Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
        PtrA := Ptr . &quot;*&quot;

        MCode_ImageSearch := &quot;
            (LTrim Join
            8b44243883ec205355565783f8010f857a0100008b7c2458897c24143b7c24600f8db50b00008b44244c8b5c245c8b
            4c24448b7424548be80fafef896c242490897424683bf30f8d0a0100008d64240033c033db8bf5896c241c895c2420894424
            183b4424480f8d0401000033c08944241085c90f8e9d0000008b5424688b7c24408beb8d34968b54246403df8d4900b80300
            0000803c18008b442410745e8b44243c0fb67c2f020fb64c06028d04113bf87f792bca3bf97c738b44243c0fb64c06018b44
            24400fb67c28018d04113bf87f5a2bca3bf97c548b44243c0fb63b0fb60c068d04113bf87f422bca3bf97c3c8b4424108b7c
            24408b4c24444083c50483c30483c604894424103bc17c818b5c24208b74241c0374244c8b44241840035c24508974241ce9
            2dffffff8b6c24688b5c245c8b4c244445896c24683beb8b6c24240f8c06ffffff8b44244c8b7c24148b7424544703e8897c
            2414896c24243b7c24600f8cd5feffffe96b0a00008b4424348b4c246889088b4424388b4c24145f5e5d890833c05b83c420
            c383f8020f85870100008b7c24604f897c24103b7c24580f8c310a00008b44244c8b5c245c8b4c24448bef0fafe8f7d88944
            24188b4424548b742418896c24288d4900894424683bc30f8d0a0100008d64240033c033db8bf5896c2420895c241c894424
            243b4424480f8d0401000033c08944241485c90f8e9d0000008b5424688b7c24408beb8d34968b54246403df8d4900b80300
            0000803c03008b442414745e8b44243c0fb67c2f020fb64c06028d04113bf87f792bca3bf97c738b44243c0fb64c06018b44
            24400fb67c28018d04113bf87f5a2bca3bf97c548b44243c0fb63b0fb60c068d04113bf87f422bca3bf97c3c8b4424148b7c
            24408b4c24444083c50483c30483c604894424143bc17c818b5c241c8b7424200374244c8b44242440035c245089742420e9
            2dffffff8b6c24688b5c245c8b4c244445896c24683beb8b6c24280f8c06ffffff8b7c24108b4424548b7424184f03ee897c
            2410896c24283b7c24580f8dd5feffffe9db0800008b4424348b4c246889088b4424388b4c24105f5e5d890833c05b83c420
            c383f8030f85650100008b7c24604f897c24103b7c24580f8ca10800008b44244c8b6c245c8b5c24548b4c24448bf70faff0
            4df7d8896c242c897424188944241c8bff896c24683beb0f8c020100008d64240033c033db89742424895c2420894424283b
            4424480f8d76ffffff33c08944241485c90f8e9f0000008b5424688b7c24408beb8d34968b54246403dfeb038d4900b80300
            0000803c03008b442414745e8b44243c0fb67c2f020fb64c06028d04113bf87f752bca3bf97c6f8b44243c0fb64c06018b44
            24400fb67c28018d04113bf87f562bca3bf97c508b44243c0fb63b0fb60c068d04113bf87f3e2bca3bf97c388b4424148b7c
            24408b4c24444083c50483c30483c604894424143bc17c818b5c24208b7424248b4424280374244c40035c2450e92bffffff
            8b6c24688b5c24548b4c24448b7424184d896c24683beb0f8d0affffff8b7c24108b44241c4f03f0897c2410897424183b7c
            24580f8c580700008b6c242ce9d4feffff83f8040f85670100008b7c2458897c24103b7c24600f8d340700008b44244c8b6c
            245c8b5c24548b4c24444d8bf00faff7896c242c8974241ceb098da424000000008bff896c24683beb0f8c020100008d6424
            0033c033db89742424895c2420894424283b4424480f8d06feffff33c08944241485c90f8e9f0000008b5424688b7c24408b
            eb8d34968b54246403dfeb038d4900b803000000803c03008b442414745e8b44243c0fb67c2f020fb64c06028d04113bf87f
            752bca3bf97c6f8b44243c0fb64c06018b4424400fb67c28018d04113bf87f562bca3bf97c508b44243c0fb63b0fb60c068d
            04113bf87f3e2bca3bf97c388b4424148b7c24408b4c24444083c50483c30483c604894424143bc17c818b5c24208b742424
            8b4424280374244c40035c2450e92bffffff8b6c24688b5c24548b4c24448b74241c4d896c24683beb0f8d0affffff8b4424
            4c8b7c24104703f0897c24108974241c3b7c24600f8de80500008b6c242ce9d4feffff83f8050f85890100008b7c2454897c
            24683b7c245c0f8dc40500008b5c24608b6c24588b44244c8b4c2444eb078da42400000000896c24103beb0f8d200100008b
            e80faf6c2458896c241c33c033db8bf5896c2424895c2420894424283b4424480f8d0d01000033c08944241485c90f8ea600
            00008b5424688b7c24408beb8d34968b54246403dfeb0a8da424000000008d4900b803000000803c03008b442414745e8b44
            243c0fb67c2f020fb64c06028d04113bf87f792bca3bf97c738b44243c0fb64c06018b4424400fb67c28018d04113bf87f5a
            2bca3bf97c548b44243c0fb63b0fb60c068d04113bf87f422bca3bf97c3c8b4424148b7c24408b4c24444083c50483c30483
            c604894424143bc17c818b5c24208b7424240374244c8b44242840035c245089742424e924ffffff8b7c24108b6c241c8b44
            244c8b5c24608b4c24444703e8897c2410896c241c3bfb0f8cf3feffff8b7c24688b6c245847897c24683b7c245c0f8cc5fe
            ffffe96b0400008b4424348b4c24688b74241089088b4424385f89305e5d33c05b83c420c383f8060f85670100008b7c2454
            897c24683b7c245c0f8d320400008b6c24608b5c24588b44244c8b4c24444d896c24188bff896c24103beb0f8c1a0100008b
            f50faff0f7d88974241c8944242ceb038d490033c033db89742424895c2420894424283b4424480f8d06fbffff33c0894424
            1485c90f8e9f0000008b5424688b7c24408beb8d34968b54246403dfeb038d4900b803000000803c03008b442414745e8b44
            243c0fb67c2f020fb64c06028d04113bf87f752bca3bf97c6f8b44243c0fb64c06018b4424400fb67c28018d04113bf87f56
            2bca3bf97c508b44243c0fb63b0fb60c068d04113bf87f3e2bca3bf97c388b4424148b7c24408b4c24444083c50483c30483
            c604894424143bc17c818b5c24208b7424248b4424280374244c40035c2450e92bffffff8b6c24108b74241c0374242c8b5c
            24588b4c24444d896c24108974241c3beb0f8d02ffffff8b44244c8b7c246847897c24683b7c245c0f8de60200008b6c2418
            e9c2feffff83f8070f85670100008b7c245c4f897c24683b7c24540f8cc10200008b6c24608b5c24588b44244c8b4c24444d
            896c241890896c24103beb0f8c1a0100008bf50faff0f7d88974241c8944242ceb038d490033c033db89742424895c242089
            4424283b4424480f8d96f9ffff33c08944241485c90f8e9f0000008b5424688b7c24408beb8d34968b54246403dfeb038d49
            00b803000000803c18008b442414745e8b44243c0fb67c2f020fb64c06028d04113bf87f752bca3bf97c6f8b44243c0fb64c
            06018b4424400fb67c28018d04113bf87f562bca3bf97c508b44243c0fb63b0fb60c068d04113bf87f3e2bca3bf97c388b44
            24148b7c24408b4c24444083c50483c30483c604894424143bc17c818b5c24208b7424248b4424280374244c40035c2450e9
            2bffffff8b6c24108b74241c0374242c8b5c24588b4c24444d896c24108974241c3beb0f8d02ffffff8b44244c8b7c24684f
            897c24683b7c24540f8c760100008b6c2418e9c2feffff83f8080f85640100008b7c245c4f897c24683b7c24540f8c510100
            008b5c24608b6c24588b44244c8b4c24448d9b00000000896c24103beb0f8d200100008be80faf6c2458896c241c33c033db
            8bf5896c2424895c2420894424283b4424480f8d9dfcffff33c08944241485c90f8ea60000008b5424688b7c24408beb8d34
            968b54246403dfeb0a8da424000000008d4900b803000000803c03008b442414745e8b44243c0fb67c2f020fb64c06028d04
            113bf87f792bca3bf97c738b44243c0fb64c06018b4424400fb67c28018d04113bf87f5a2bca3bf97c548b44243c0fb63b0f
            b604068d0c103bf97f422bc23bf87c3c8b4424148b7c24408b4c24444083c50483c30483c604894424143bc17c818b5c2420
            8b7424240374244c8b44242840035c245089742424e924ffffff8b7c24108b6c241c8b44244c8b5c24608b4c24444703e889
            7c2410896c241c3bfb0f8cf3feffff8b7c24688b6c24584f897c24683b7c24540f8dc5feffff8b4424345fc700ffffffff8b
            4424345e5dc700ffffffffb85ff0ffff5b83c420c3,4c894c24204c89442418488954241048894c24085355565741544
            155415641574883ec188b8424c80000004d8bd94d8bd0488bda83f8010f85b3010000448b8c24a800000044890c24443b8c2
            4b80000000f8d66010000448bac24900000008b9424c0000000448b8424b00000008bbc2480000000448b9424a0000000418
            bcd410fafc9894c24040f1f84000000000044899424c8000000453bd00f8dfb000000468d2495000000000f1f80000000003
            3ed448bf933f6660f1f8400000000003bac24880000000f8d1701000033db85ff7e7e458bf4448bce442bf64503f7904d63c
            14d03c34180780300745a450fb65002438d040e4c63d84c035c2470410fb64b028d0411443bd07f572bca443bd17c50410fb
            64b01450fb650018d0411443bd07f3e2bca443bd17c37410fb60b450fb6108d0411443bd07f272bca443bd17c204c8b5c247
            8ffc34183c1043bdf7c8fffc54503fd03b42498000000e95effffff8b8424c8000000448b8424b00000008b4c24044c8b5c2
            478ffc04183c404898424c8000000413bc00f8c20ffffff448b0c24448b9424a000000041ffc14103cd44890c24894c24044
            43b8c24b80000000f8cd8feffff488b5c2468488b4c2460b85ff0ffffc701ffffffffc703ffffffff4883c418415f415e415
            d415c5f5e5d5bc38b8424c8000000e9860b000083f8020f858c010000448b8c24b800000041ffc944890c24443b8c24a8000
            0007cab448bac2490000000448b8424c00000008b9424b00000008bbc2480000000448b9424a0000000418bc9410fafcd418
            bc5894c2404f7d8894424080f1f400044899424c8000000443bd20f8d02010000468d2495000000000f1f80000000004533f
            6448bf933f60f1f840000000000443bb424880000000f8d56ffffff33db85ff0f8e81000000418bec448bd62bee4103ef496
            3d24903d3807a03007460440fb64a02418d042a4c63d84c035c2470410fb64b02428d0401443bc87f5d412bc8443bc97c554
            10fb64b01440fb64a01428d0401443bc87f42412bc8443bc97c3a410fb60b440fb60a428d0401443bc87f29412bc8443bc97
            c214c8b5c2478ffc34183c2043bdf7c8a41ffc64503fd03b42498000000e955ffffff8b8424c80000008b9424b00000008b4
            c24044c8b5c2478ffc04183c404898424c80000003bc20f8c19ffffff448b0c24448b9424a0000000034c240841ffc9894c2
            40444890c24443b8c24a80000000f8dd0feffffe933feffff83f8030f85c4010000448b8c24b800000041ffc944898c24c80
            00000443b8c24a80000000f8c0efeffff8b842490000000448b9c24b0000000448b8424c00000008bbc248000000041ffcb4
            18bc98bd044895c24080fafc8f7da890c24895424048b9424a0000000448b542404458beb443bda0f8c13010000468d249d0
            000000066660f1f84000000000033ed448bf933f6660f1f8400000000003bac24880000000f8d0801000033db85ff0f8e960
            00000488b4c2478458bf4448bd6442bf64503f70f1f8400000000004963d24803d1807a03007460440fb64a02438d04164c6
            3d84c035c2470410fb64b02428d0401443bc87f63412bc8443bc97c5b410fb64b01440fb64a01428d0401443bc87f48412bc
            8443bc97c40410fb60b440fb60a428d0401443bc87f2f412bc8443bc97c27488b4c2478ffc34183c2043bdf7c8a8b8424900
            00000ffc54403f803b42498000000e942ffffff8b9424a00000008b8424900000008b0c2441ffcd4183ec04443bea0f8d11f
            fffff448b8c24c8000000448b542404448b5c240841ffc94103ca44898c24c8000000890c24443b8c24a80000000f8dc2fef
            fffe983fcffff488b4c24608b8424c8000000448929488b4c2468890133c0e981fcffff83f8040f857f010000448b8c24a80
            0000044890c24443b8c24b80000000f8d48fcffff448bac2490000000448b9424b00000008b9424c0000000448b8424a0000
            0008bbc248000000041ffca418bcd4489542408410fafc9894c2404669044899424c8000000453bd00f8cf8000000468d249
            5000000000f1f800000000033ed448bf933f6660f1f8400000000003bac24880000000f8df7fbffff33db85ff7e7e458bf44
            48bce442bf64503f7904d63c14d03c34180780300745a450fb65002438d040e4c63d84c035c2470410fb64b028d0411443bd
            07f572bca443bd17c50410fb64b01450fb650018d0411443bd07f3e2bca443bd17c37410fb60b450fb6108d0411443bd07f2
            72bca443bd17c204c8b5c2478ffc34183c1043bdf7c8fffc54503fd03b42498000000e95effffff8b8424c8000000448b842
            4a00000008b4c24044c8b5c2478ffc84183ec04898424c8000000413bc00f8d20ffffff448b0c24448b54240841ffc14103c
            d44890c24894c2404443b8c24b80000000f8cdbfeffffe9defaffff83f8050f85ab010000448b8424a000000044890424443
            b8424b00000000f8dc0faffff8b9424c0000000448bac2498000000448ba424900000008bbc2480000000448b8c24a800000
            0428d0c8500000000898c24c800000044894c2404443b8c24b80000000f8d09010000418bc4410fafc18944240833ed448bf
            833f6660f1f8400000000003bac24880000000f8d0501000033db85ff0f8e87000000448bf1448bce442bf64503f74d63c14
            d03c34180780300745d438d040e4c63d84d03da450fb65002410fb64b028d0411443bd07f5f2bca443bd17c58410fb64b014
            50fb650018d0411443bd07f462bca443bd17c3f410fb60b450fb6108d0411443bd07f2f2bca443bd17c284c8b5c24784c8b5
            42470ffc34183c1043bdf7c8c8b8c24c8000000ffc54503fc4103f5e955ffffff448b4424048b4424088b8c24c80000004c8
            b5c24784c8b54247041ffc04103c4448944240489442408443b8424b80000000f8c0effffff448b0424448b8c24a80000004
            1ffc083c10444890424898c24c8000000443b8424b00000000f8cc5feffffe946f9ffff488b4c24608b042489018b4424044
            88b4c2468890133c0e945f9ffff83f8060f85aa010000448b8c24a000000044894c2404443b8c24b00000000f8d0bf9ffff8
            b8424b8000000448b8424c0000000448ba424900000008bbc2480000000428d0c8d00000000ffc88944240c898c24c800000
            06666660f1f840000000000448be83b8424a80000000f8c02010000410fafc4418bd4f7da891424894424084533f6448bf83
            3f60f1f840000000000443bb424880000000f8df900000033db85ff0f8e870000008be9448bd62bee4103ef4963d24903d38
            07a03007460440fb64a02418d042a4c63d84c035c2470410fb64b02428d0401443bc87f64412bc8443bc97c5c410fb64b014
            40fb64a01428d0401443bc87f49412bc8443bc97c41410fb60b440fb60a428d0401443bc87f30412bc8443bc97c284c8b5c2
            478ffc34183c2043bdf7c8a8b8c24c800000041ffc64503fc03b42498000000e94fffffff8b4424088b8c24c80000004c8b5
            c247803042441ffcd89442408443bac24a80000000f8d17ffffff448b4c24048b44240c41ffc183c10444894c2404898c24c
            8000000443b8c24b00000000f8ccefeffffe991f7ffff488b4c24608b4424048901488b4c246833c0448929e992f7ffff83f
            8070f858d010000448b8c24b000000041ffc944894c2404443b8c24a00000000f8c55f7ffff8b8424b8000000448b8424c00
            00000448ba424900000008bbc2480000000428d0c8d00000000ffc8890424898c24c8000000660f1f440000448be83b8424a
            80000000f8c02010000410fafc4418bd4f7da8954240c8944240833ed448bf833f60f1f8400000000003bac24880000000f8
            d4affffff33db85ff0f8e89000000448bf1448bd6442bf64503f74963d24903d3807a03007460440fb64a02438d04164c63d
            84c035c2470410fb64b02428d0401443bc87f63412bc8443bc97c5b410fb64b01440fb64a01428d0401443bc87f48412bc84
            43bc97c40410fb60b440fb60a428d0401443bc87f2f412bc8443bc97c274c8b5c2478ffc34183c2043bdf7c8a8b8c24c8000
            000ffc54503fc03b42498000000e94fffffff8b4424088b8c24c80000004c8b5c24780344240c41ffcd89442408443bac24a
            80000000f8d17ffffff448b4c24048b042441ffc983e90444894c2404898c24c8000000443b8c24a00000000f8dcefeffffe
            9e1f5ffff83f8080f85ddf5ffff448b8424b000000041ffc84489442404443b8424a00000000f8cbff5ffff8b9424c000000
            0448bac2498000000448ba424900000008bbc2480000000448b8c24a8000000428d0c8500000000898c24c800000044890c2
            4443b8c24b80000000f8d08010000418bc4410fafc18944240833ed448bf833f6660f1f8400000000003bac24880000000f8
            d0501000033db85ff0f8e87000000448bf1448bce442bf64503f74d63c14d03c34180780300745d438d040e4c63d84d03da4
            50fb65002410fb64b028d0411443bd07f5f2bca443bd17c58410fb64b01450fb650018d0411443bd07f462bca443bd17c3f4
            10fb603450fb6108d0c10443bd17f2f2bc2443bd07c284c8b5c24784c8b542470ffc34183c1043bdf7c8c8b8c24c8000000f
            fc54503fc4103f5e955ffffff448b04248b4424088b8c24c80000004c8b5c24784c8b54247041ffc04103c44489042489442
            408443b8424b80000000f8c10ffffff448b442404448b8c24a800000041ffc883e9044489442404898c24c8000000443b842
            4a00000000f8dc6feffffe946f4ffff8b442404488b4c246089018b0424488b4c2468890133c0e945f4ffff
            )&quot;
        if ( A_PtrSize == 8 ) ; x64, after comma
            MCode_ImageSearch := SubStr(MCode_ImageSearch,InStr(MCode_ImageSearch,&quot;,&quot;)+1)
        else ; x86, before comma
            MCode_ImageSearch := SubStr(MCode_ImageSearch,1,InStr(MCode_ImageSearch,&quot;,&quot;)-1)
        VarSetCapacity(_ImageSearch, LEN := StrLen(MCode_ImageSearch)//2, 0)
        Loop, %LEN%
            NumPut(&quot;0x&quot; . SubStr(MCode_ImageSearch,(2*A_Index)-1,2), _ImageSearch, A_Index-1, &quot;uchar&quot;)
        MCode_ImageSearch := &quot;&quot;
        DllCall(&quot;VirtualProtect&quot;, Ptr,&amp;_ImageSearch, Ptr,VarSetCapacity(_ImageSearch), &quot;uint&quot;,0x40, PtrA,0)
    }

    ; Abort if an initial coordinates is located before a final coordinate
    If ( sx2 &lt; sx1 )
        return -3001
    If ( sy2 &lt; sy1 )
        return -3002

    ; Check the search box. &quot;sx2,sy2&quot; will be the last pixel evaluated
    ; as possibly matching with the needle&#039;s first pixel. So, we must
    ; avoid going beyond this maximum final coordinate.
    If ( sx2 &gt; (hWidth-nWidth+1) )
        return -3003
    If ( sy2 &gt; (hHeight-nHeight+1) )
        return -3004

    ; Abort if the width or height of the search box is 0
    If ( sx2-sx1 == 0 )
        return -3005
    If ( sy2-sy1 == 0 )
        return -3006

    ; The DllCall parameters are the same for easier C code modification,
    ; even though they aren&#039;t all used on the _ImageSearch version
    x := 0, y := 0
    , E := DllCall( &amp;_ImageSearch, &quot;int*&quot;,x, &quot;int*&quot;,y, Ptr,hScan, Ptr,nScan, &quot;int&quot;,nWidth, &quot;int&quot;,nHeight
    , &quot;int&quot;,hStride, &quot;int&quot;,nStride, &quot;int&quot;,sx1, &quot;int&quot;,sy1, &quot;int&quot;,sx2, &quot;int&quot;,sy2, &quot;int&quot;,Variation
    , &quot;int&quot;,sd, &quot;cdecl int&quot;)
    Return ( E == &quot;&quot; ? -3007 : E )
}







; Gdip standard library v1.45 by tic (Tariq Porter) 07/09/11
; Modifed by Rseding91 using fincs 64 bit compatible Gdip library 5/1/2013
; Supports: Basic, _L ANSi, _L Unicode x86 and _L Unicode x64
;
; Updated 2/20/2014 - fixed Gdip_CreateRegion() and Gdip_GetClipRegion() on AHK Unicode x86
; Updated 5/13/2013 - fixed Gdip_SetBitmapToClipboard() on AHK Unicode x64
;
;#####################################################################################
;#####################################################################################
; STATUS ENUMERATION
; Return values for functions specified to have status enumerated return type
;#####################################################################################
;
; Ok =						= 0
; GenericError				= 1
; InvalidParameter			= 2
; OutOfMemory				= 3
; ObjectBusy				= 4
; InsufficientBuffer		= 5
; NotImplemented			= 6
; Win32Error				= 7
; WrongState				= 8
; Aborted					= 9
; FileNotFound				= 10
; ValueOverflow				= 11
; AccessDenied				= 12
; UnknownImageFormat		= 13
; FontFamilyNotFound		= 14
; FontStyleNotFound			= 15
; NotTrueTypeFont			= 16
; UnsupportedGdiplusVersion	= 17
; GdiplusNotInitialized		= 18
; PropertyNotFound			= 19
; PropertyNotSupported		= 20
; ProfileNotFound			= 21
;
;#####################################################################################
;#####################################################################################
; FUNCTIONS
;#####################################################################################
;
; UpdateLayeredWindow(hwnd, hdc, x=&quot;&quot;, y=&quot;&quot;, w=&quot;&quot;, h=&quot;&quot;, Alpha=255)
; BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster=&quot;&quot;)
; StretchBlt(dDC, dx, dy, dw, dh, sDC, sx, sy, sw, sh, Raster=&quot;&quot;)
; SetImage(hwnd, hBitmap)
; Gdip_BitmapFromScreen(Screen=0, Raster=&quot;&quot;)
; CreateRectF(ByRef RectF, x, y, w, h)
; CreateSizeF(ByRef SizeF, w, h)
; CreateDIBSection
;
;#####################################################################################

; Function:     			UpdateLayeredWindow
; Description:  			Updates a layered window with the handle to the DC of a gdi bitmap
; 
; hwnd        				Handle of the layered window to update
; hdc           			Handle to the DC of the GDI bitmap to update the window with
; Layeredx      			x position to place the window
; Layeredy      			y position to place the window
; Layeredw      			Width of the window
; Layeredh      			Height of the window
; Alpha         			Default = 255 : The transparency (0-255) to set the window transparency
;
; return      				If the function succeeds, the return value is nonzero
;
; notes						If x or y omitted, then layered window will use its current coordinates
;							If w or h omitted then current width and height will be used

UpdateLayeredWindow(hwnd, hdc, x=&quot;&quot;, y=&quot;&quot;, w=&quot;&quot;, h=&quot;&quot;, Alpha=255)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	if ((x != &quot;&quot;) &amp;&amp; (y != &quot;&quot;))
		VarSetCapacity(pt, 8), NumPut(x, pt, 0, &quot;UInt&quot;), NumPut(y, pt, 4, &quot;UInt&quot;)

	if (w = &quot;&quot;) ||(h = &quot;&quot;)
		WinGetPos,,, w, h, ahk_id %hwnd%
   
	return DllCall(&quot;UpdateLayeredWindow&quot;
					, Ptr, hwnd
					, Ptr, 0
					, Ptr, ((x = &quot;&quot;) &amp;&amp; (y = &quot;&quot;)) ? 0 : &amp;pt
					, &quot;int64*&quot;, w|h&lt;&lt;32
					, Ptr, hdc
					, &quot;int64*&quot;, 0
					, &quot;uint&quot;, 0
					, &quot;UInt*&quot;, Alpha&lt;&lt;16|1&lt;&lt;24
					, &quot;uint&quot;, 2)
}

;#####################################################################################

; Function				BitBlt
; Description			The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle 
;						of pixels from the specified source device context into a destination device context.
;
; dDC					handle to destination DC
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of the area to copy
; dh					height of the area to copy
; sDC					handle to source DC
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; Raster				raster operation code
;
; return				If the function succeeds, the return value is nonzero
;
; notes					If no raster operation is specified, then SRCCOPY is used, which copies the source directly to the destination rectangle
;
; BLACKNESS				= 0x00000042
; NOTSRCERASE			= 0x001100A6
; NOTSRCCOPY			= 0x00330008
; SRCERASE				= 0x00440328
; DSTINVERT				= 0x00550009
; PATINVERT				= 0x005A0049
; SRCINVERT				= 0x00660046
; SRCAND				= 0x008800C6
; MERGEPAINT			= 0x00BB0226
; MERGECOPY				= 0x00C000CA
; SRCCOPY				= 0x00CC0020
; SRCPAINT				= 0x00EE0086
; PATCOPY				= 0x00F00021
; PATPAINT				= 0x00FB0A09
; WHITENESS				= 0x00FF0062
; CAPTUREBLT			= 0x40000000
; NOMIRRORBITMAP		= 0x80000000

BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster=&quot;&quot;)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdi32\BitBlt&quot;
					, Ptr, dDC
					, &quot;int&quot;, dx
					, &quot;int&quot;, dy
					, &quot;int&quot;, dw
					, &quot;int&quot;, dh
					, Ptr, sDC
					, &quot;int&quot;, sx
					, &quot;int&quot;, sy
					, &quot;uint&quot;, Raster ? Raster : 0x00CC0020)
}

;#####################################################################################

; Function				StretchBlt
; Description			The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle, 
;						stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary.
;						The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context.
;
; ddc					handle to destination DC
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of destination rectangle
; dh					height of destination rectangle
; sdc					handle to source DC
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source rectangle
; sh					height of source rectangle
; Raster				raster operation code
;
; return				If the function succeeds, the return value is nonzero
;
; notes					If no raster operation is specified, then SRCCOPY is used. It uses the same raster operations as BitBlt		

StretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster=&quot;&quot;)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdi32\StretchBlt&quot;
					, Ptr, ddc
					, &quot;int&quot;, dx
					, &quot;int&quot;, dy
					, &quot;int&quot;, dw
					, &quot;int&quot;, dh
					, Ptr, sdc
					, &quot;int&quot;, sx
					, &quot;int&quot;, sy
					, &quot;int&quot;, sw
					, &quot;int&quot;, sh
					, &quot;uint&quot;, Raster ? Raster : 0x00CC0020)
}

;#####################################################################################

; Function				SetStretchBltMode
; Description			The SetStretchBltMode function sets the bitmap stretching mode in the specified device context
;
; hdc					handle to the DC
; iStretchMode			The stretching mode, describing how the target will be stretched
;
; return				If the function succeeds, the return value is the previous stretching mode. If it fails it will return 0
;
; STRETCH_ANDSCANS 		= 0x01
; STRETCH_ORSCANS 		= 0x02
; STRETCH_DELETESCANS 	= 0x03
; STRETCH_HALFTONE 		= 0x04

SetStretchBltMode(hdc, iStretchMode=4)
{
	return DllCall(&quot;gdi32\SetStretchBltMode&quot;
					, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hdc
					, &quot;int&quot;, iStretchMode)
}

;#####################################################################################

; Function				SetImage
; Description			Associates a new image with a static control
;
; hwnd					handle of the control to update
; hBitmap				a gdi bitmap to associate the static control with
;
; return				If the function succeeds, the return value is nonzero

SetImage(hwnd, hBitmap)
{
	SendMessage, 0x172, 0x0, hBitmap,, ahk_id %hwnd%
	E := ErrorLevel
	DeleteObject(E)
	return E
}

;#####################################################################################

; Function				SetSysColorToControl
; Description			Sets a solid colour to a control
;
; hwnd					handle of the control to update
; SysColor				A system colour to set to the control
;
; return				If the function succeeds, the return value is zero
;
; notes					A control must have the 0xE style set to it so it is recognised as a bitmap
;						By default SysColor=15 is used which is COLOR_3DFACE. This is the standard background for a control
;
; COLOR_3DDKSHADOW				= 21
; COLOR_3DFACE					= 15
; COLOR_3DHIGHLIGHT				= 20
; COLOR_3DHILIGHT				= 20
; COLOR_3DLIGHT					= 22
; COLOR_3DSHADOW				= 16
; COLOR_ACTIVEBORDER			= 10
; COLOR_ACTIVECAPTION			= 2
; COLOR_APPWORKSPACE			= 12
; COLOR_BACKGROUND				= 1
; COLOR_BTNFACE					= 15
; COLOR_BTNHIGHLIGHT			= 20
; COLOR_BTNHILIGHT				= 20
; COLOR_BTNSHADOW				= 16
; COLOR_BTNTEXT					= 18
; COLOR_CAPTIONTEXT				= 9
; COLOR_DESKTOP					= 1
; COLOR_GRADIENTACTIVECAPTION	= 27
; COLOR_GRADIENTINACTIVECAPTION	= 28
; COLOR_GRAYTEXT				= 17
; COLOR_HIGHLIGHT				= 13
; COLOR_HIGHLIGHTTEXT			= 14
; COLOR_HOTLIGHT				= 26
; COLOR_INACTIVEBORDER			= 11
; COLOR_INACTIVECAPTION			= 3
; COLOR_INACTIVECAPTIONTEXT		= 19
; COLOR_INFOBK					= 24
; COLOR_INFOTEXT				= 23
; COLOR_MENU					= 4
; COLOR_MENUHILIGHT				= 29
; COLOR_MENUBAR					= 30
; COLOR_MENUTEXT				= 7
; COLOR_SCROLLBAR				= 0
; COLOR_WINDOW					= 5
; COLOR_WINDOWFRAME				= 6
; COLOR_WINDOWTEXT				= 8

SetSysColorToControl(hwnd, SysColor=15)
{
   WinGetPos,,, w, h, ahk_id %hwnd%
   bc := DllCall(&quot;GetSysColor&quot;, &quot;Int&quot;, SysColor, &quot;UInt&quot;)
   pBrushClear := Gdip_BrushCreateSolid(0xff000000 | (bc &gt;&gt; 16 | bc &amp; 0xff00 | (bc &amp; 0xff) &lt;&lt; 16))
   pBitmap := Gdip_CreateBitmap(w, h), G := Gdip_GraphicsFromImage(pBitmap)
   Gdip_FillRectangle(G, pBrushClear, 0, 0, w, h)
   hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
   SetImage(hwnd, hBitmap)
   Gdip_DeleteBrush(pBrushClear)
   Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
   return 0
}

;#####################################################################################

; Function				Gdip_BitmapFromScreen
; Description			Gets a gdi+ bitmap from the screen
;
; Screen				0 = All screens
;						Any numerical value = Just that screen
;						x|y|w|h = Take specific coordinates with a width and height
; Raster				raster operation code
;
; return      			If the function succeeds, the return value is a pointer to a gdi+ bitmap
;						-1:		one or more of x,y,w,h not passed properly
;
; notes					If no raster operation is specified, then SRCCOPY is used to the returned bitmap

Gdip_BitmapFromScreen(Screen=0, Raster=&quot;&quot;)
{
	if (Screen = 0)
	{
		Sysget, x, 76
		Sysget, y, 77	
		Sysget, w, 78
		Sysget, h, 79
	}
	else if (SubStr(Screen, 1, 5) = &quot;hwnd:&quot;)
	{
		Screen := SubStr(Screen, 6)
		if !WinExist( &quot;ahk_id &quot; Screen)
			return -2
		WinGetPos,,, w, h, ahk_id %Screen%
		x := y := 0
		hhdc := GetDCEx(Screen, 3)
	}
	else if (Screen&amp;1 != &quot;&quot;)
	{
		Sysget, M, Monitor, %Screen%
		x := MLeft, y := MTop, w := MRight-MLeft, h := MBottom-MTop
	}
	else
	{
		StringSplit, S, Screen, |
		x := S1, y := S2, w := S3, h := S4
	}

	if (x = &quot;&quot;) || (y = &quot;&quot;) || (w = &quot;&quot;) || (h = &quot;&quot;)
		return -1

	chdc := CreateCompatibleDC(), hbm := CreateDIBSection(w, h, chdc), obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
	BitBlt(chdc, 0, 0, w, h, hhdc, x, y, Raster)
	ReleaseDC(hhdc)
	
	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
	SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
	return pBitmap
}

;#####################################################################################

; Function				Gdip_BitmapFromHWND
; Description			Uses PrintWindow to get a handle to the specified window and return a bitmap from it
;
; hwnd					handle to the window to get a bitmap from
;
; return				If the function succeeds, the return value is a pointer to a gdi+ bitmap
;
; notes					Window must not be not minimised in order to get a handle to it&#039;s client area

Gdip_BitmapFromHWND(hwnd)
{
	WinGetPos,,, Width, Height, ahk_id %hwnd%
	hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
	PrintWindow(hwnd, hdc)
	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
	SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
	return pBitmap
}

;#####################################################################################

; Function    			CreateRectF
; Description			Creates a RectF object, containing a the coordinates and dimensions of a rectangle
;
; RectF       			Name to call the RectF object
; x            			x-coordinate of the upper left corner of the rectangle
; y            			y-coordinate of the upper left corner of the rectangle
; w            			Width of the rectangle
; h            			Height of the rectangle
;
; return      			No return value

CreateRectF(ByRef RectF, x, y, w, h)
{
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, &quot;float&quot;), NumPut(y, RectF, 4, &quot;float&quot;), NumPut(w, RectF, 8, &quot;float&quot;), NumPut(h, RectF, 12, &quot;float&quot;)
}

;#####################################################################################

; Function    			CreateRect
; Description			Creates a Rect object, containing a the coordinates and dimensions of a rectangle
;
; RectF       			Name to call the RectF object
; x            			x-coordinate of the upper left corner of the rectangle
; y            			y-coordinate of the upper left corner of the rectangle
; w            			Width of the rectangle
; h            			Height of the rectangle
;
; return      			No return value

CreateRect(ByRef Rect, x, y, w, h)
{
	VarSetCapacity(Rect, 16)
	NumPut(x, Rect, 0, &quot;uint&quot;), NumPut(y, Rect, 4, &quot;uint&quot;), NumPut(w, Rect, 8, &quot;uint&quot;), NumPut(h, Rect, 12, &quot;uint&quot;)
}
;#####################################################################################

; Function		    	CreateSizeF
; Description			Creates a SizeF object, containing an 2 values
;
; SizeF         		Name to call the SizeF object
; w            			w-value for the SizeF object
; h            			h-value for the SizeF object
;
; return      			No Return value

CreateSizeF(ByRef SizeF, w, h)
{
   VarSetCapacity(SizeF, 8)
   NumPut(w, SizeF, 0, &quot;float&quot;), NumPut(h, SizeF, 4, &quot;float&quot;)     
}
;#####################################################################################

; Function		    	CreatePointF
; Description			Creates a SizeF object, containing an 2 values
;
; SizeF         		Name to call the SizeF object
; w            			w-value for the SizeF object
; h            			h-value for the SizeF object
;
; return      			No Return value

CreatePointF(ByRef PointF, x, y)
{
   VarSetCapacity(PointF, 8)
   NumPut(x, PointF, 0, &quot;float&quot;), NumPut(y, PointF, 4, &quot;float&quot;)     
}
;#####################################################################################

; Function				CreateDIBSection
; Description			The CreateDIBSection function creates a DIB (Device Independent Bitmap) that applications can write to directly
;
; w						width of the bitmap to create
; h						height of the bitmap to create
; hdc					a handle to the device context to use the palette from
; bpp					bits per pixel (32 = ARGB)
; ppvBits				A pointer to a variable that receives a pointer to the location of the DIB bit values
;
; return				returns a DIB. A gdi bitmap
;
; notes					ppvBits will receive the location of the pixels in the DIB

CreateDIBSection(w, h, hdc=&quot;&quot;, bpp=32, ByRef ppvBits=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)
	
	NumPut(w, bi, 4, &quot;uint&quot;)
	, NumPut(h, bi, 8, &quot;uint&quot;)
	, NumPut(40, bi, 0, &quot;uint&quot;)
	, NumPut(1, bi, 12, &quot;ushort&quot;)
	, NumPut(0, bi, 16, &quot;uInt&quot;)
	, NumPut(bpp, bi, 14, &quot;ushort&quot;)
	
	hbm := DllCall(&quot;CreateDIBSection&quot;
					, Ptr, hdc2
					, Ptr, &amp;bi
					, &quot;uint&quot;, 0
					, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, ppvBits
					, Ptr, 0
					, &quot;uint&quot;, 0, Ptr)

	if !hdc
		ReleaseDC(hdc2)
	return hbm
}

;#####################################################################################

; Function				PrintWindow
; Description			The PrintWindow function copies a visual window into the specified device context (DC), typically a printer DC
;
; hwnd					A handle to the window that will be copied
; hdc					A handle to the device context
; Flags					Drawing options
;
; return				If the function succeeds, it returns a nonzero value
;
; PW_CLIENTONLY			= 1

PrintWindow(hwnd, hdc, Flags=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;PrintWindow&quot;, Ptr, hwnd, Ptr, hdc, &quot;uint&quot;, Flags)
}

;#####################################################################################

; Function				DestroyIcon
; Description			Destroys an icon and frees any memory the icon occupied
;
; hIcon					Handle to the icon to be destroyed. The icon must not be in use
;
; return				If the function succeeds, the return value is nonzero

DestroyIcon(hIcon)
{
	return DllCall(&quot;DestroyIcon&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hIcon)
}

;#####################################################################################

PaintDesktop(hdc)
{
	return DllCall(&quot;PaintDesktop&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hdc)
}

;#####################################################################################

CreateCompatibleBitmap(hdc, w, h)
{
	return DllCall(&quot;gdi32\CreateCompatibleBitmap&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hdc, &quot;int&quot;, w, &quot;int&quot;, h)
}

;#####################################################################################

; Function				CreateCompatibleDC
; Description			This function creates a memory device context (DC) compatible with the specified device
;
; hdc					Handle to an existing device context					
;
; return				returns the handle to a device context or 0 on failure
;
; notes					If this handle is 0 (by default), the function creates a memory device context compatible with the application&#039;s current screen

CreateCompatibleDC(hdc=0)
{
   return DllCall(&quot;CreateCompatibleDC&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hdc)
}

;#####################################################################################

; Function				SelectObject
; Description			The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type
;
; hdc					Handle to a DC
; hgdiobj				A handle to the object to be selected into the DC
;
; return				If the selected object is not a region and the function succeeds, the return value is a handle to the object being replaced
;
; notes					The specified object must have been created by using one of the following functions
;						Bitmap - CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, CreateDIBitmap, CreateDIBSection (A single bitmap cannot be selected into more than one DC at the same time)
;						Brush - CreateBrushIndirect, CreateDIBPatternBrush, CreateDIBPatternBrushPt, CreateHatchBrush, CreatePatternBrush, CreateSolidBrush
;						Font - CreateFont, CreateFontIndirect
;						Pen - CreatePen, CreatePenIndirect
;						Region - CombineRgn, CreateEllipticRgn, CreateEllipticRgnIndirect, CreatePolygonRgn, CreateRectRgn, CreateRectRgnIndirect
;
; notes					If the selected object is a region and the function succeeds, the return value is one of the following value
;
; SIMPLEREGION			= 2 Region consists of a single rectangle
; COMPLEXREGION			= 3 Region consists of more than one rectangle
; NULLREGION			= 1 Region is empty

SelectObject(hdc, hgdiobj)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;SelectObject&quot;, Ptr, hdc, Ptr, hgdiobj)
}

;#####################################################################################

; Function				DeleteObject
; Description			This function deletes a logical pen, brush, font, bitmap, region, or palette, freeing all system resources associated with the object
;						After the object is deleted, the specified handle is no longer valid
;
; hObject				Handle to a logical pen, brush, font, bitmap, region, or palette to delete
;
; return				Nonzero indicates success. Zero indicates that the specified handle is not valid or that the handle is currently selected into a device context

DeleteObject(hObject)
{
   return DllCall(&quot;DeleteObject&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hObject)
}

;#####################################################################################

; Function				GetDC
; Description			This function retrieves a handle to a display device context (DC) for the client area of the specified window.
;						The display device context can be used in subsequent graphics display interface (GDI) functions to draw in the client area of the window. 
;
; hwnd					Handle to the window whose device context is to be retrieved. If this value is NULL, GetDC retrieves the device context for the entire screen					
;
; return				The handle the device context for the specified window&#039;s client area indicates success. NULL indicates failure

GetDC(hwnd=0)
{
	return DllCall(&quot;GetDC&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hwnd)
}

;#####################################################################################

; DCX_CACHE = 0x2
; DCX_CLIPCHILDREN = 0x8
; DCX_CLIPSIBLINGS = 0x10
; DCX_EXCLUDERGN = 0x40
; DCX_EXCLUDEUPDATE = 0x100
; DCX_INTERSECTRGN = 0x80
; DCX_INTERSECTUPDATE = 0x200
; DCX_LOCKWINDOWUPDATE = 0x400
; DCX_NORECOMPUTE = 0x100000
; DCX_NORESETATTRS = 0x4
; DCX_PARENTCLIP = 0x20
; DCX_VALIDATE = 0x200000
; DCX_WINDOW = 0x1

GetDCEx(hwnd, flags=0, hrgnClip=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
    return DllCall(&quot;GetDCEx&quot;, Ptr, hwnd, Ptr, hrgnClip, &quot;int&quot;, flags)
}

;#####################################################################################

; Function				ReleaseDC
; Description			This function releases a device context (DC), freeing it for use by other applications. The effect of ReleaseDC depends on the type of device context
;
; hdc					Handle to the device context to be released
; hwnd					Handle to the window whose device context is to be released
;
; return				1 = released
;						0 = not released
;
; notes					The application must call the ReleaseDC function for each call to the GetWindowDC function and for each call to the GetDC function that retrieves a common device context
;						An application cannot use the ReleaseDC function to release a device context that was created by calling the CreateDC function; instead, it must use the DeleteDC function. 

ReleaseDC(hdc, hwnd=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;ReleaseDC&quot;, Ptr, hwnd, Ptr, hdc)
}

;#####################################################################################

; Function				DeleteDC
; Description			The DeleteDC function deletes the specified device context (DC)
;
; hdc					A handle to the device context
;
; return				If the function succeeds, the return value is nonzero
;
; notes					An application must not delete a DC whose handle was obtained by calling the GetDC function. Instead, it must call the ReleaseDC function to free the DC

DeleteDC(hdc)
{
   return DllCall(&quot;DeleteDC&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hdc)
}
;#####################################################################################

; Function				Gdip_LibraryVersion
; Description			Get the current library version
;
; return				the library version
;
; notes					This is useful for non compiled programs to ensure that a person doesn&#039;t run an old version when testing your scripts

Gdip_LibraryVersion()
{
	return 1.45
}

;#####################################################################################

; Function				Gdip_LibrarySubVersion
; Description			Get the current library sub version
;
; return				the library sub version
;
; notes					This is the sub-version currently maintained by Rseding91
Gdip_LibrarySubVersion()
{
	return 1.47
}

;#####################################################################################

; Function:    			Gdip_BitmapFromBRA
; Description: 			Gets a pointer to a gdi+ bitmap from a BRA file
;
; BRAFromMemIn			The variable for a BRA file read to memory
; File					The name of the file, or its number that you would like (This depends on alternate parameter)
; Alternate				Changes whether the File parameter is the file name or its number
;
; return      			If the function succeeds, the return value is a pointer to a gdi+ bitmap
;						-1 = The BRA variable is empty
;						-2 = The BRA has an incorrect header
;						-3 = The BRA has information missing
;						-4 = Could not find file inside the BRA

Gdip_BitmapFromBRA(ByRef BRAFromMemIn, File, Alternate=0)
{
	Static FName = &quot;ObjRelease&quot;
	
	if !BRAFromMemIn
		return -1
	Loop, Parse, BRAFromMemIn, `n
	{
		if (A_Index = 1)
		{
			StringSplit, Header, A_LoopField, |
			if (Header0 != 4 || Header2 != &quot;BRA!&quot;)
				return -2
		}
		else if (A_Index = 2)
		{
			StringSplit, Info, A_LoopField, |
			if (Info0 != 3)
				return -3
		}
		else
			break
	}
	if !Alternate
		StringReplace, File, File, \, \\, All
	RegExMatch(BRAFromMemIn, &quot;mi`n)^&quot; (Alternate ? File &quot;\|.+?\|(\d+)\|(\d+)&quot; : &quot;\d+\|&quot; File &quot;\|(\d+)\|(\d+)&quot;) &quot;$&quot;, FileInfo)
	if !FileInfo
		return -4
	
	hData := DllCall(&quot;GlobalAlloc&quot;, &quot;uint&quot;, 2, Ptr, FileInfo2, Ptr)
	pData := DllCall(&quot;GlobalLock&quot;, Ptr, hData, Ptr)
	DllCall(&quot;RtlMoveMemory&quot;, Ptr, pData, Ptr, &amp;BRAFromMemIn+Info2+FileInfo1, Ptr, FileInfo2)
	DllCall(&quot;GlobalUnlock&quot;, Ptr, hData)
	DllCall(&quot;ole32\CreateStreamOnHGlobal&quot;, Ptr, hData, &quot;int&quot;, 1, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pStream)
	DllCall(&quot;gdiplus\GdipCreateBitmapFromStream&quot;, Ptr, pStream, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pBitmap)
	If (A_PtrSize)
		%FName%(pStream)
	Else
		DllCall(NumGet(NumGet(1*pStream)+8), &quot;uint&quot;, pStream)
	return pBitmap
}

;#####################################################################################

; Function				Gdip_DrawRectangle
; Description			This function uses a pen to draw the outline of a rectangle into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rectangle
; y						y-coordinate of the top left of the rectangle
; w						width of the rectanlge
; h						height of the rectangle
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipDrawRectangle&quot;, Ptr, pGraphics, Ptr, pPen, &quot;float&quot;, x, &quot;float&quot;, y, &quot;float&quot;, w, &quot;float&quot;, h)
}

;#####################################################################################

; Function				Gdip_DrawRoundedRectangle
; Description			This function uses a pen to draw the outline of a rounded rectangle into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rounded rectangle
; y						y-coordinate of the top left of the rounded rectangle
; w						width of the rectanlge
; h						height of the rectangle
; r						radius of the rounded corners
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r)
{
	Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
	E := Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
	Gdip_ResetClip(pGraphics)
	Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
	Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
	Gdip_DrawEllipse(pGraphics, pPen, x, y, 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y, 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x, y+h-(2*r), 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
	Gdip_ResetClip(pGraphics)
	return E
}

;#####################################################################################

; Function				Gdip_DrawEllipse
; Description			This function uses a pen to draw the outline of an ellipse into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rectangle the ellipse will be drawn into
; y						y-coordinate of the top left of the rectangle the ellipse will be drawn into
; w						width of the ellipse
; h						height of the ellipse
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawEllipse(pGraphics, pPen, x, y, w, h)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipDrawEllipse&quot;, Ptr, pGraphics, Ptr, pPen, &quot;float&quot;, x, &quot;float&quot;, y, &quot;float&quot;, w, &quot;float&quot;, h)
}

;#####################################################################################

; Function				Gdip_DrawBezier
; Description			This function uses a pen to draw the outline of a bezier (a weighted curve) into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x1					x-coordinate of the start of the bezier
; y1					y-coordinate of the start of the bezier
; x2					x-coordinate of the first arc of the bezier
; y2					y-coordinate of the first arc of the bezier
; x3					x-coordinate of the second arc of the bezier
; y3					y-coordinate of the second arc of the bezier
; x4					x-coordinate of the end of the bezier
; y4					y-coordinate of the end of the bezier
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawBezier(pGraphics, pPen, x1, y1, x2, y2, x3, y3, x4, y4)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipDrawBezier&quot;
					, Ptr, pgraphics
					, Ptr, pPen
					, &quot;float&quot;, x1
					, &quot;float&quot;, y1
					, &quot;float&quot;, x2
					, &quot;float&quot;, y2
					, &quot;float&quot;, x3
					, &quot;float&quot;, y3
					, &quot;float&quot;, x4
					, &quot;float&quot;, y4)
}

;#####################################################################################

; Function				Gdip_DrawArc
; Description			This function uses a pen to draw the outline of an arc into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the start of the arc
; y						y-coordinate of the start of the arc
; w						width of the arc
; h						height of the arc
; StartAngle			specifies the angle between the x-axis and the starting point of the arc
; SweepAngle			specifies the angle between the starting and ending points of the arc
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawArc(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipDrawArc&quot;
					, Ptr, pGraphics
					, Ptr, pPen
					, &quot;float&quot;, x
					, &quot;float&quot;, y
					, &quot;float&quot;, w
					, &quot;float&quot;, h
					, &quot;float&quot;, StartAngle
					, &quot;float&quot;, SweepAngle)
}

;#####################################################################################

; Function				Gdip_DrawPie
; Description			This function uses a pen to draw the outline of a pie into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the start of the pie
; y						y-coordinate of the start of the pie
; w						width of the pie
; h						height of the pie
; StartAngle			specifies the angle between the x-axis and the starting point of the pie
; SweepAngle			specifies the angle between the starting and ending points of the pie
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawPie(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipDrawPie&quot;, Ptr, pGraphics, Ptr, pPen, &quot;float&quot;, x, &quot;float&quot;, y, &quot;float&quot;, w, &quot;float&quot;, h, &quot;float&quot;, StartAngle, &quot;float&quot;, SweepAngle)
}

;#####################################################################################

; Function				Gdip_DrawLine
; Description			This function uses a pen to draw a line into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x1					x-coordinate of the start of the line
; y1					y-coordinate of the start of the line
; x2					x-coordinate of the end of the line
; y2					y-coordinate of the end of the line
;
; return				status enumeration. 0 = success		

Gdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipDrawLine&quot;
					, Ptr, pGraphics
					, Ptr, pPen
					, &quot;float&quot;, x1
					, &quot;float&quot;, y1
					, &quot;float&quot;, x2
					, &quot;float&quot;, y2)
}

;#####################################################################################

; Function				Gdip_DrawLines
; Description			This function uses a pen to draw a series of joined lines into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; Points				the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return				status enumeration. 0 = success				

Gdip_DrawLines(pGraphics, pPen, Points)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	StringSplit, Points, Points, |
	VarSetCapacity(PointF, 8*Points0)   
	Loop, %Points0%
	{
		StringSplit, Coord, Points%A_Index%, `,
		NumPut(Coord1, PointF, 8*(A_Index-1), &quot;float&quot;), NumPut(Coord2, PointF, (8*(A_Index-1))+4, &quot;float&quot;)
	}
	return DllCall(&quot;gdiplus\GdipDrawLines&quot;, Ptr, pGraphics, Ptr, pPen, Ptr, &amp;PointF, &quot;int&quot;, Points0)
}

;#####################################################################################

; Function				Gdip_FillRectangle
; Description			This function uses a brush to fill a rectangle in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the rectangle
; y						y-coordinate of the top left of the rectangle
; w						width of the rectanlge
; h						height of the rectangle
;
; return				status enumeration. 0 = success

Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipFillRectangle&quot;
					, Ptr, pGraphics
					, Ptr, pBrush
					, &quot;float&quot;, x
					, &quot;float&quot;, y
					, &quot;float&quot;, w
					, &quot;float&quot;, h)
}

;#####################################################################################

; Function				Gdip_FillRoundedRectangle
; Description			This function uses a brush to fill a rounded rectangle in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the rounded rectangle
; y						y-coordinate of the top left of the rounded rectangle
; w						width of the rectanlge
; h						height of the rectangle
; r						radius of the rounded corners
;
; return				status enumeration. 0 = success

Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)
{
	Region := Gdip_GetClipRegion(pGraphics)
	Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
	E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
	Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
	Gdip_FillEllipse(pGraphics, pBrush, x, y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_DeleteRegion(Region)
	return E
}

;#####################################################################################

; Function				Gdip_FillPolygon
; Description			This function uses a brush to fill a polygon in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; Points				the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return				status enumeration. 0 = success
;
; notes					Alternate will fill the polygon as a whole, wheras winding will fill each new &quot;segment&quot;
; Alternate 			= 0
; Winding 				= 1

Gdip_FillPolygon(pGraphics, pBrush, Points, FillMode=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	StringSplit, Points, Points, |
	VarSetCapacity(PointF, 8*Points0)   
	Loop, %Points0%
	{
		StringSplit, Coord, Points%A_Index%, `,
		NumPut(Coord1, PointF, 8*(A_Index-1), &quot;float&quot;), NumPut(Coord2, PointF, (8*(A_Index-1))+4, &quot;float&quot;)
	}   
	return DllCall(&quot;gdiplus\GdipFillPolygon&quot;, Ptr, pGraphics, Ptr, pBrush, Ptr, &amp;PointF, &quot;int&quot;, Points0, &quot;int&quot;, FillMode)
}

;#####################################################################################

; Function				Gdip_FillPie
; Description			This function uses a brush to fill a pie in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the pie
; y						y-coordinate of the top left of the pie
; w						width of the pie
; h						height of the pie
; StartAngle			specifies the angle between the x-axis and the starting point of the pie
; SweepAngle			specifies the angle between the starting and ending points of the pie
;
; return				status enumeration. 0 = success

Gdip_FillPie(pGraphics, pBrush, x, y, w, h, StartAngle, SweepAngle)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipFillPie&quot;
					, Ptr, pGraphics
					, Ptr, pBrush
					, &quot;float&quot;, x
					, &quot;float&quot;, y
					, &quot;float&quot;, w
					, &quot;float&quot;, h
					, &quot;float&quot;, StartAngle
					, &quot;float&quot;, SweepAngle)
}

;#####################################################################################

; Function				Gdip_FillEllipse
; Description			This function uses a brush to fill an ellipse in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the ellipse
; y						y-coordinate of the top left of the ellipse
; w						width of the ellipse
; h						height of the ellipse
;
; return				status enumeration. 0 = success

Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipFillEllipse&quot;, Ptr, pGraphics, Ptr, pBrush, &quot;float&quot;, x, &quot;float&quot;, y, &quot;float&quot;, w, &quot;float&quot;, h)
}

;#####################################################################################

; Function				Gdip_FillRegion
; Description			This function uses a brush to fill a region in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; Region				Pointer to a Region
;
; return				status enumeration. 0 = success
;
; notes					You can create a region Gdip_CreateRegion() and then add to this

Gdip_FillRegion(pGraphics, pBrush, Region)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipFillRegion&quot;, Ptr, pGraphics, Ptr, pBrush, Ptr, Region)
}

;#####################################################################################

; Function				Gdip_FillPath
; Description			This function uses a brush to fill a path in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; Region				Pointer to a Path
;
; return				status enumeration. 0 = success

Gdip_FillPath(pGraphics, pBrush, Path)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipFillPath&quot;, Ptr, pGraphics, Ptr, pBrush, Ptr, Path)
}

;#####################################################################################

; Function				Gdip_DrawImagePointsRect
; Description			This function draws a bitmap into the Graphics of another bitmap and skews it
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBitmap				Pointer to a bitmap to be drawn
; Points				Points passed as x1,y1|x2,y2|x3,y3 (3 points: top left, top right, bottom left) describing the drawing of the bitmap
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source rectangle
; sh					height of source rectangle
; Matrix				a matrix used to alter image attributes when drawing
;
; return				status enumeration. 0 = success
;
; notes					if sx,sy,sw,sh are missed then the entire source bitmap will be used
;						Matrix can be omitted to just draw with no alteration to ARGB
;						Matrix may be passed as a digit from 0 - 1 to change just transparency
;						Matrix can be passed as a matrix with any delimiter

Gdip_DrawImagePointsRect(pGraphics, pBitmap, Points, sx=&quot;&quot;, sy=&quot;&quot;, sw=&quot;&quot;, sh=&quot;&quot;, Matrix=1)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	StringSplit, Points, Points, |
	VarSetCapacity(PointF, 8*Points0)   
	Loop, %Points0%
	{
		StringSplit, Coord, Points%A_Index%, `,
		NumPut(Coord1, PointF, 8*(A_Index-1), &quot;float&quot;), NumPut(Coord2, PointF, (8*(A_Index-1))+4, &quot;float&quot;)
	}

	if (Matrix&amp;1 = &quot;&quot;)
		ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
	else if (Matrix != 1)
		ImageAttr := Gdip_SetImageAttributesColorMatrix(&quot;1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|&quot; Matrix &quot;|0|0|0|0|0|1&quot;)
		
	if (sx = &quot;&quot; &amp;&amp; sy = &quot;&quot; &amp;&amp; sw = &quot;&quot; &amp;&amp; sh = &quot;&quot;)
	{
		sx := 0, sy := 0
		sw := Gdip_GetImageWidth(pBitmap)
		sh := Gdip_GetImageHeight(pBitmap)
	}

	E := DllCall(&quot;gdiplus\GdipDrawImagePointsRect&quot;
				, Ptr, pGraphics
				, Ptr, pBitmap
				, Ptr, &amp;PointF
				, &quot;int&quot;, Points0
				, &quot;float&quot;, sx
				, &quot;float&quot;, sy
				, &quot;float&quot;, sw
				, &quot;float&quot;, sh
				, &quot;int&quot;, 2
				, Ptr, ImageAttr
				, Ptr, 0
				, Ptr, 0)
	if ImageAttr
		Gdip_DisposeImageAttributes(ImageAttr)
	return E
}

;#####################################################################################

; Function				Gdip_DrawImage
; Description			This function draws a bitmap into the Graphics of another bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBitmap				Pointer to a bitmap to be drawn
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of destination image
; dh					height of destination image
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source image
; sh					height of source image
; Matrix				a matrix used to alter image attributes when drawing
;
; return				status enumeration. 0 = success
;
; notes					if sx,sy,sw,sh are missed then the entire source bitmap will be used
;						Gdip_DrawImage performs faster
;						Matrix can be omitted to just draw with no alteration to ARGB
;						Matrix may be passed as a digit from 0 - 1 to change just transparency
;						Matrix can be passed as a matrix with any delimiter. For example:
;						MatrixBright=
;						(
;						1.5		|0		|0		|0		|0
;						0		|1.5	|0		|0		|0
;						0		|0		|1.5	|0		|0
;						0		|0		|0		|1		|0
;						0.05	|0.05	|0.05	|0		|1
;						)
;
; notes					MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1
;						MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1
;						MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|0|0|0|0|1

Gdip_DrawImage(pGraphics, pBitmap, dx=&quot;&quot;, dy=&quot;&quot;, dw=&quot;&quot;, dh=&quot;&quot;, sx=&quot;&quot;, sy=&quot;&quot;, sw=&quot;&quot;, sh=&quot;&quot;, Matrix=1)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	if (Matrix&amp;1 = &quot;&quot;)
		ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
	else if (Matrix != 1)
		ImageAttr := Gdip_SetImageAttributesColorMatrix(&quot;1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|&quot; Matrix &quot;|0|0|0|0|0|1&quot;)

	if (sx = &quot;&quot; &amp;&amp; sy = &quot;&quot; &amp;&amp; sw = &quot;&quot; &amp;&amp; sh = &quot;&quot;)
	{
		if (dx = &quot;&quot; &amp;&amp; dy = &quot;&quot; &amp;&amp; dw = &quot;&quot; &amp;&amp; dh = &quot;&quot;)
		{
			sx := dx := 0, sy := dy := 0
			sw := dw := Gdip_GetImageWidth(pBitmap)
			sh := dh := Gdip_GetImageHeight(pBitmap)
		}
		else
		{
			sx := sy := 0
			sw := Gdip_GetImageWidth(pBitmap)
			sh := Gdip_GetImageHeight(pBitmap)
		}
	}

	E := DllCall(&quot;gdiplus\GdipDrawImageRectRect&quot;
				, Ptr, pGraphics
				, Ptr, pBitmap
				, &quot;float&quot;, dx
				, &quot;float&quot;, dy
				, &quot;float&quot;, dw
				, &quot;float&quot;, dh
				, &quot;float&quot;, sx
				, &quot;float&quot;, sy
				, &quot;float&quot;, sw
				, &quot;float&quot;, sh
				, &quot;int&quot;, 2
				, Ptr, ImageAttr
				, Ptr, 0
				, Ptr, 0)
	if ImageAttr
		Gdip_DisposeImageAttributes(ImageAttr)
	return E
}

;#####################################################################################

; Function				Gdip_SetImageAttributesColorMatrix
; Description			This function creates an image matrix ready for drawing
;
; Matrix				a matrix used to alter image attributes when drawing
;						passed with any delimeter
;
; return				returns an image matrix on sucess or 0 if it fails
;
; notes					MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1
;						MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1
;						MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|0|0|0|0|1

Gdip_SetImageAttributesColorMatrix(Matrix)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	VarSetCapacity(ColourMatrix, 100, 0)
	Matrix := RegExReplace(RegExReplace(Matrix, &quot;^[^\d-\.]+([\d\.])&quot;, &quot;$1&quot;, &quot;&quot;, 1), &quot;[^\d-\.]+&quot;, &quot;|&quot;)
	StringSplit, Matrix, Matrix, |
	Loop, 25
	{
		Matrix := (Matrix%A_Index% != &quot;&quot;) ? Matrix%A_Index% : Mod(A_Index-1, 6) ? 0 : 1
		NumPut(Matrix, ColourMatrix, (A_Index-1)*4, &quot;float&quot;)
	}
	DllCall(&quot;gdiplus\GdipCreateImageAttributes&quot;, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, ImageAttr)
	DllCall(&quot;gdiplus\GdipSetImageAttributesColorMatrix&quot;, Ptr, ImageAttr, &quot;int&quot;, 1, &quot;int&quot;, 1, Ptr, &amp;ColourMatrix, Ptr, 0, &quot;int&quot;, 0)
	return ImageAttr
}

;#####################################################################################

; Function				Gdip_GraphicsFromImage
; Description			This function gets the graphics for a bitmap used for drawing functions
;
; pBitmap				Pointer to a bitmap to get the pointer to its graphics
;
; return				returns a pointer to the graphics of a bitmap
;
; notes					a bitmap can be drawn into the graphics of another bitmap

Gdip_GraphicsFromImage(pBitmap)
{
	DllCall(&quot;gdiplus\GdipGetImageGraphicsContext&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pGraphics)
	return pGraphics
}

;#####################################################################################

; Function				Gdip_GraphicsFromHDC
; Description			This function gets the graphics from the handle to a device context
;
; hdc					This is the handle to the device context
;
; return				returns a pointer to the graphics of a bitmap
;
; notes					You can draw a bitmap into the graphics of another bitmap

Gdip_GraphicsFromHDC(hdc)
{
    DllCall(&quot;gdiplus\GdipCreateFromHDC&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hdc, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pGraphics)
    return pGraphics
}

;#####################################################################################

; Function				Gdip_GetDC
; Description			This function gets the device context of the passed Graphics
;
; hdc					This is the handle to the device context
;
; return				returns the device context for the graphics of a bitmap

Gdip_GetDC(pGraphics)
{
	DllCall(&quot;gdiplus\GdipGetDC&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, hdc)
	return hdc
}

;#####################################################################################

; Function				Gdip_ReleaseDC
; Description			This function releases a device context from use for further use
;
; pGraphics				Pointer to the graphics of a bitmap
; hdc					This is the handle to the device context
;
; return				status enumeration. 0 = success

Gdip_ReleaseDC(pGraphics, hdc)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipReleaseDC&quot;, Ptr, pGraphics, Ptr, hdc)
}

;#####################################################################################

; Function				Gdip_GraphicsClear
; Description			Clears the graphics of a bitmap ready for further drawing
;
; pGraphics				Pointer to the graphics of a bitmap
; ARGB					The colour to clear the graphics to
;
; return				status enumeration. 0 = success
;
; notes					By default this will make the background invisible
;						Using clipping regions you can clear a particular area on the graphics rather than clearing the entire graphics

Gdip_GraphicsClear(pGraphics, ARGB=0x00ffffff)
{
    return DllCall(&quot;gdiplus\GdipGraphicsClear&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;int&quot;, ARGB)
}

;#####################################################################################

; Function				Gdip_BlurBitmap
; Description			Gives a pointer to a blurred bitmap from a pointer to a bitmap
;
; pBitmap				Pointer to a bitmap to be blurred
; Blur					The Amount to blur a bitmap by from 1 (least blur) to 100 (most blur)
;
; return				If the function succeeds, the return value is a pointer to the new blurred bitmap
;						-1 = The blur parameter is outside the range 1-100
;
; notes					This function will not dispose of the original bitmap

Gdip_BlurBitmap(pBitmap, Blur)
{
	if (Blur &gt; 100) || (Blur &lt; 1)
		return -1	
	
	sWidth := Gdip_GetImageWidth(pBitmap), sHeight := Gdip_GetImageHeight(pBitmap)
	dWidth := sWidth//Blur, dHeight := sHeight//Blur

	pBitmap1 := Gdip_CreateBitmap(dWidth, dHeight)
	G1 := Gdip_GraphicsFromImage(pBitmap1)
	Gdip_SetInterpolationMode(G1, 7)
	Gdip_DrawImage(G1, pBitmap, 0, 0, dWidth, dHeight, 0, 0, sWidth, sHeight)

	Gdip_DeleteGraphics(G1)

	pBitmap2 := Gdip_CreateBitmap(sWidth, sHeight)
	G2 := Gdip_GraphicsFromImage(pBitmap2)
	Gdip_SetInterpolationMode(G2, 7)
	Gdip_DrawImage(G2, pBitmap1, 0, 0, sWidth, sHeight, 0, 0, dWidth, dHeight)

	Gdip_DeleteGraphics(G2)
	Gdip_DisposeImage(pBitmap1)
	return pBitmap2
}

;#####################################################################################

; Function:     		Gdip_SaveBitmapToFile
; Description:  		Saves a bitmap to a file in any supported format onto disk
;   
; pBitmap				Pointer to a bitmap
; sOutput      			The name of the file that the bitmap will be saved to. Supported extensions are: .BMP,.DIB,.RLE,.JPG,.JPEG,.JPE,.JFIF,.GIF,.TIF,.TIFF,.PNG
; Quality      			If saving as jpg (.JPG,.JPEG,.JPE,.JFIF) then quality can be 1-100 with default at maximum quality
;
; return      			If the function succeeds, the return value is zero, otherwise:
;						-1 = Extension supplied is not a supported file format
;						-2 = Could not get a list of encoders on system
;						-3 = Could not find matching encoder for specified file format
;						-4 = Could not get WideChar name of output file
;						-5 = Could not save file to disk
;
; notes					This function will use the extension supplied from the sOutput parameter to determine the output format

Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality=75)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	SplitPath, sOutput,,, Extension
	if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
		return -1
	Extension := &quot;.&quot; Extension

	DllCall(&quot;gdiplus\GdipGetImageEncodersSize&quot;, &quot;uint*&quot;, nCount, &quot;uint*&quot;, nSize)
	VarSetCapacity(ci, nSize)
	DllCall(&quot;gdiplus\GdipGetImageEncoders&quot;, &quot;uint&quot;, nCount, &quot;uint&quot;, nSize, Ptr, &amp;ci)
	if !(nCount &amp;&amp; nSize)
		return -2
	
	If (A_IsUnicode){
		StrGet_Name := &quot;StrGet&quot;
		Loop, %nCount%
		{
			sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), &quot;UTF-16&quot;)
			if !InStr(sString, &quot;*&quot; Extension)
				continue
			
			pCodec := &amp;ci+idx
			break
		}
	} else {
		Loop, %nCount%
		{
			Location := NumGet(ci, 76*(A_Index-1)+44)
			nSize := DllCall(&quot;WideCharToMultiByte&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, &quot;uint&quot;, Location, &quot;int&quot;, -1, &quot;uint&quot;, 0, &quot;int&quot;,  0, &quot;uint&quot;, 0, &quot;uint&quot;, 0)
			VarSetCapacity(sString, nSize)
			DllCall(&quot;WideCharToMultiByte&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, &quot;uint&quot;, Location, &quot;int&quot;, -1, &quot;str&quot;, sString, &quot;int&quot;, nSize, &quot;uint&quot;, 0, &quot;uint&quot;, 0)
			if !InStr(sString, &quot;*&quot; Extension)
				continue
			
			pCodec := &amp;ci+76*(A_Index-1)
			break
		}
	}
	
	if !pCodec
		return -3

	if (Quality != 75)
	{
		Quality := (Quality &lt; 0) ? 0 : (Quality &gt; 100) ? 100 : Quality
		if Extension in .JPG,.JPEG,.JPE,.JFIF
		{
			DllCall(&quot;gdiplus\GdipGetEncoderParameterListSize&quot;, Ptr, pBitmap, Ptr, pCodec, &quot;uint*&quot;, nSize)
			VarSetCapacity(EncoderParameters, nSize, 0)
			DllCall(&quot;gdiplus\GdipGetEncoderParameterList&quot;, Ptr, pBitmap, Ptr, pCodec, &quot;uint&quot;, nSize, Ptr, &amp;EncoderParameters)
			Loop, % NumGet(EncoderParameters, &quot;UInt&quot;)      ;%
			{
				elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
				if (NumGet(EncoderParameters, elem+16, &quot;UInt&quot;) = 1) &amp;&amp; (NumGet(EncoderParameters, elem+20, &quot;UInt&quot;) = 6)
				{
					p := elem+&amp;EncoderParameters-pad-4
					NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, &quot;UInt&quot;)), &quot;UInt&quot;)
					break
				}
			}      
		}
	}

	if (!A_IsUnicode)
	{
		nSize := DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;sOutput, &quot;int&quot;, -1, Ptr, 0, &quot;int&quot;, 0)
		VarSetCapacity(wOutput, nSize*2)
		DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;sOutput, &quot;int&quot;, -1, Ptr, &amp;wOutput, &quot;int&quot;, nSize)
		VarSetCapacity(wOutput, -1)
		if !VarSetCapacity(wOutput)
			return -4
		E := DllCall(&quot;gdiplus\GdipSaveImageToFile&quot;, Ptr, pBitmap, Ptr, &amp;wOutput, Ptr, pCodec, &quot;uint&quot;, p ? p : 0)
	}
	else
		E := DllCall(&quot;gdiplus\GdipSaveImageToFile&quot;, Ptr, pBitmap, Ptr, &amp;sOutput, Ptr, pCodec, &quot;uint&quot;, p ? p : 0)
	return E ? -5 : 0
}

;#####################################################################################

; Function				Gdip_GetPixel
; Description			Gets the ARGB of a pixel in a bitmap
;
; pBitmap				Pointer to a bitmap
; x						x-coordinate of the pixel
; y						y-coordinate of the pixel
;
; return				Returns the ARGB value of the pixel

Gdip_GetPixel(pBitmap, x, y)
{
	DllCall(&quot;gdiplus\GdipBitmapGetPixel&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, &quot;int&quot;, x, &quot;int&quot;, y, &quot;uint*&quot;, ARGB)
	return ARGB
}

;#####################################################################################

; Function				Gdip_SetPixel
; Description			Sets the ARGB of a pixel in a bitmap
;
; pBitmap				Pointer to a bitmap
; x						x-coordinate of the pixel
; y						y-coordinate of the pixel
;
; return				status enumeration. 0 = success

Gdip_SetPixel(pBitmap, x, y, ARGB)
{
   return DllCall(&quot;gdiplus\GdipBitmapSetPixel&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, &quot;int&quot;, x, &quot;int&quot;, y, &quot;int&quot;, ARGB)
}

;#####################################################################################

; Function				Gdip_GetImageWidth
; Description			Gives the width of a bitmap
;
; pBitmap				Pointer to a bitmap
;
; return				Returns the width in pixels of the supplied bitmap

Gdip_GetImageWidth(pBitmap)
{
   DllCall(&quot;gdiplus\GdipGetImageWidth&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, &quot;uint*&quot;, Width)
   return Width
}

;#####################################################################################

; Function				Gdip_GetImageHeight
; Description			Gives the height of a bitmap
;
; pBitmap				Pointer to a bitmap
;
; return				Returns the height in pixels of the supplied bitmap

Gdip_GetImageHeight(pBitmap)
{
   DllCall(&quot;gdiplus\GdipGetImageHeight&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, &quot;uint*&quot;, Height)
   return Height
}

;#####################################################################################

; Function				Gdip_GetDimensions
; Description			Gives the width and height of a bitmap
;
; pBitmap				Pointer to a bitmap
; Width					ByRef variable. This variable will be set to the width of the bitmap
; Height				ByRef variable. This variable will be set to the height of the bitmap
;
; return				No return value
;						Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the height

Gdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	DllCall(&quot;gdiplus\GdipGetImageWidth&quot;, Ptr, pBitmap, &quot;uint*&quot;, Width)
	DllCall(&quot;gdiplus\GdipGetImageHeight&quot;, Ptr, pBitmap, &quot;uint*&quot;, Height)
}

;#####################################################################################

Gdip_GetDimensions(pBitmap, ByRef Width, ByRef Height)
{
	Gdip_GetImageDimensions(pBitmap, Width, Height)
}

;#####################################################################################

Gdip_GetImagePixelFormat(pBitmap)
{
	DllCall(&quot;gdiplus\GdipGetImagePixelFormat&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, Format)
	return Format
}

;#####################################################################################

; Function				Gdip_GetDpiX
; Description			Gives the horizontal dots per inch of the graphics of a bitmap
;
; pBitmap				Pointer to a bitmap
; Width					ByRef variable. This variable will be set to the width of the bitmap
; Height				ByRef variable. This variable will be set to the height of the bitmap
;
; return				No return value
;						Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the height

Gdip_GetDpiX(pGraphics)
{
	DllCall(&quot;gdiplus\GdipGetDpiX&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;uint&quot;, pGraphics, &quot;float*&quot;, dpix)
	return Round(dpix)
}

;#####################################################################################

Gdip_GetDpiY(pGraphics)
{
	DllCall(&quot;gdiplus\GdipGetDpiY&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;uint&quot;, pGraphics, &quot;float*&quot;, dpiy)
	return Round(dpiy)
}

;#####################################################################################

Gdip_GetImageHorizontalResolution(pBitmap)
{
	DllCall(&quot;gdiplus\GdipGetImageHorizontalResolution&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;uint&quot;, pBitmap, &quot;float*&quot;, dpix)
	return Round(dpix)
}

;#####################################################################################

Gdip_GetImageVerticalResolution(pBitmap)
{
	DllCall(&quot;gdiplus\GdipGetImageVerticalResolution&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;uint&quot;, pBitmap, &quot;float*&quot;, dpiy)
	return Round(dpiy)
}

;#####################################################################################

Gdip_BitmapSetResolution(pBitmap, dpix, dpiy)
{
	return DllCall(&quot;gdiplus\GdipBitmapSetResolution&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;uint&quot;, pBitmap, &quot;float&quot;, dpix, &quot;float&quot;, dpiy)
}

;#####################################################################################

Gdip_CreateBitmapFromFile(sFile, IconNumber=1, IconSize=&quot;&quot;)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	, PtrA := A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;
	
	SplitPath, sFile,,, ext
	if ext in exe,dll
	{
		Sizes := IconSize ? IconSize : 256 &quot;|&quot; 128 &quot;|&quot; 64 &quot;|&quot; 48 &quot;|&quot; 32 &quot;|&quot; 16
		BufSize := 16 + (2*(A_PtrSize ? A_PtrSize : 4))
		
		VarSetCapacity(buf, BufSize, 0)
		Loop, Parse, Sizes, |
		{
			DllCall(&quot;PrivateExtractIcons&quot;, &quot;str&quot;, sFile, &quot;int&quot;, IconNumber-1, &quot;int&quot;, A_LoopField, &quot;int&quot;, A_LoopField, PtrA, hIcon, PtrA, 0, &quot;uint&quot;, 1, &quot;uint&quot;, 0)
			
			if !hIcon
				continue

			if !DllCall(&quot;GetIconInfo&quot;, Ptr, hIcon, Ptr, &amp;buf)
			{
				DestroyIcon(hIcon)
				continue
			}
			
			hbmMask  := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4))
			hbmColor := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4) + (A_PtrSize ? A_PtrSize : 4))
			if !(hbmColor &amp;&amp; DllCall(&quot;GetObject&quot;, Ptr, hbmColor, &quot;int&quot;, BufSize, Ptr, &amp;buf))
			{
				DestroyIcon(hIcon)
				continue
			}
			break
		}
		if !hIcon
			return -1

		Width := NumGet(buf, 4, &quot;int&quot;), Height := NumGet(buf, 8, &quot;int&quot;)
		hbm := CreateDIBSection(Width, -Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
		if !DllCall(&quot;DrawIconEx&quot;, Ptr, hdc, &quot;int&quot;, 0, &quot;int&quot;, 0, Ptr, hIcon, &quot;uint&quot;, Width, &quot;uint&quot;, Height, &quot;uint&quot;, 0, Ptr, 0, &quot;uint&quot;, 3)
		{
			DestroyIcon(hIcon)
			return -2
		}
		
		VarSetCapacity(dib, 104)
		DllCall(&quot;GetObject&quot;, Ptr, hbm, &quot;int&quot;, A_PtrSize = 8 ? 104 : 84, Ptr, &amp;dib) ; sizeof(DIBSECTION) = 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize
		Stride := NumGet(dib, 12, &quot;Int&quot;), Bits := NumGet(dib, 20 + (A_PtrSize = 8 ? 4 : 0)) ; padding
		DllCall(&quot;gdiplus\GdipCreateBitmapFromScan0&quot;, &quot;int&quot;, Width, &quot;int&quot;, Height, &quot;int&quot;, Stride, &quot;int&quot;, 0x26200A, Ptr, Bits, PtrA, pBitmapOld)
		pBitmap := Gdip_CreateBitmap(Width, Height)
		G := Gdip_GraphicsFromImage(pBitmap)
		, Gdip_DrawImage(G, pBitmapOld, 0, 0, Width, Height, 0, 0, Width, Height)
		SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
		Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmapOld)
		DestroyIcon(hIcon)
	}
	else
	{
		if (!A_IsUnicode)
		{
			VarSetCapacity(wFile, 1024)
			DllCall(&quot;kernel32\MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;sFile, &quot;int&quot;, -1, Ptr, &amp;wFile, &quot;int&quot;, 512)
			DllCall(&quot;gdiplus\GdipCreateBitmapFromFile&quot;, Ptr, &amp;wFile, PtrA, pBitmap)
		}
		else
			DllCall(&quot;gdiplus\GdipCreateBitmapFromFile&quot;, Ptr, &amp;sFile, PtrA, pBitmap)
	}
	
	return pBitmap
}

;#####################################################################################

Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	DllCall(&quot;gdiplus\GdipCreateBitmapFromHBITMAP&quot;, Ptr, hBitmap, Ptr, Palette, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, pBitmap)
	return pBitmap
}

;#####################################################################################

Gdip_CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff)
{
	DllCall(&quot;gdiplus\GdipCreateHBITMAPFromBitmap&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, hbm, &quot;int&quot;, Background)
	return hbm
}

;#####################################################################################

Gdip_CreateBitmapFromHICON(hIcon)
{
	DllCall(&quot;gdiplus\GdipCreateBitmapFromHICON&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hIcon, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, pBitmap)
	return pBitmap
}

;#####################################################################################

Gdip_CreateHICONFromBitmap(pBitmap)
{
	DllCall(&quot;gdiplus\GdipCreateHICONFromBitmap&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, hIcon)
	return hIcon
}

;#####################################################################################

Gdip_CreateBitmap(Width, Height, Format=0x26200A)
{
    DllCall(&quot;gdiplus\GdipCreateBitmapFromScan0&quot;, &quot;int&quot;, Width, &quot;int&quot;, Height, &quot;int&quot;, 0, &quot;int&quot;, Format, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, 0, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, pBitmap)
    Return pBitmap
}

;#####################################################################################

Gdip_CreateBitmapFromClipboard()
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	if !DllCall(&quot;OpenClipboard&quot;, Ptr, 0)
		return -1
	if !DllCall(&quot;IsClipboardFormatAvailable&quot;, &quot;uint&quot;, 8)
		return -2
	if !hBitmap := DllCall(&quot;GetClipboardData&quot;, &quot;uint&quot;, 2, Ptr)
		return -3
	if !pBitmap := Gdip_CreateBitmapFromHBITMAP(hBitmap)
		return -4
	if !DllCall(&quot;CloseClipboard&quot;)
		return -5
	DeleteObject(hBitmap)
	return pBitmap
}

;#####################################################################################

Gdip_SetBitmapToClipboard(pBitmap)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	off1 := A_PtrSize = 8 ? 52 : 44, off2 := A_PtrSize = 8 ? 32 : 24
	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
	DllCall(&quot;GetObject&quot;, Ptr, hBitmap, &quot;int&quot;, VarSetCapacity(oi, A_PtrSize = 8 ? 104 : 84, 0), Ptr, &amp;oi)
	hdib := DllCall(&quot;GlobalAlloc&quot;, &quot;uint&quot;, 2, Ptr, 40+NumGet(oi, off1, &quot;UInt&quot;), Ptr)
	pdib := DllCall(&quot;GlobalLock&quot;, Ptr, hdib, Ptr)
	DllCall(&quot;RtlMoveMemory&quot;, Ptr, pdib, Ptr, &amp;oi+off2, Ptr, 40)
	DllCall(&quot;RtlMoveMemory&quot;, Ptr, pdib+40, Ptr, NumGet(oi, off2 - (A_PtrSize ? A_PtrSize : 4), Ptr), Ptr, NumGet(oi, off1, &quot;UInt&quot;))
	DllCall(&quot;GlobalUnlock&quot;, Ptr, hdib)
	DllCall(&quot;DeleteObject&quot;, Ptr, hBitmap)
	DllCall(&quot;OpenClipboard&quot;, Ptr, 0)
	DllCall(&quot;EmptyClipboard&quot;)
	DllCall(&quot;SetClipboardData&quot;, &quot;uint&quot;, 8, Ptr, hdib)
	DllCall(&quot;CloseClipboard&quot;)
}

;#####################################################################################

Gdip_CloneBitmapArea(pBitmap, x, y, w, h, Format=0x26200A)
{
	DllCall(&quot;gdiplus\GdipCloneBitmapArea&quot;
					, &quot;float&quot;, x
					, &quot;float&quot;, y
					, &quot;float&quot;, w
					, &quot;float&quot;, h
					, &quot;int&quot;, Format
					, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap
					, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pBitmapDest)
	return pBitmapDest
}

;#####################################################################################
; Create resources
;#####################################################################################

Gdip_CreatePen(ARGB, w)
{
   DllCall(&quot;gdiplus\GdipCreatePen1&quot;, &quot;UInt&quot;, ARGB, &quot;float&quot;, w, &quot;int&quot;, 2, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pPen)
   return pPen
}

;#####################################################################################

Gdip_CreatePenFromBrush(pBrush, w)
{
	DllCall(&quot;gdiplus\GdipCreatePen2&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBrush, &quot;float&quot;, w, &quot;int&quot;, 2, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pPen)
	return pPen
}

;#####################################################################################

Gdip_BrushCreateSolid(ARGB=0xff000000)
{
	DllCall(&quot;gdiplus\GdipCreateSolidFill&quot;, &quot;UInt&quot;, ARGB, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pBrush)
	return pBrush
}

;#####################################################################################

; HatchStyleHorizontal = 0
; HatchStyleVertical = 1
; HatchStyleForwardDiagonal = 2
; HatchStyleBackwardDiagonal = 3
; HatchStyleCross = 4
; HatchStyleDiagonalCross = 5
; HatchStyle05Percent = 6
; HatchStyle10Percent = 7
; HatchStyle20Percent = 8
; HatchStyle25Percent = 9
; HatchStyle30Percent = 10
; HatchStyle40Percent = 11
; HatchStyle50Percent = 12
; HatchStyle60Percent = 13
; HatchStyle70Percent = 14
; HatchStyle75Percent = 15
; HatchStyle80Percent = 16
; HatchStyle90Percent = 17
; HatchStyleLightDownwardDiagonal = 18
; HatchStyleLightUpwardDiagonal = 19
; HatchStyleDarkDownwardDiagonal = 20
; HatchStyleDarkUpwardDiagonal = 21
; HatchStyleWideDownwardDiagonal = 22
; HatchStyleWideUpwardDiagonal = 23
; HatchStyleLightVertical = 24
; HatchStyleLightHorizontal = 25
; HatchStyleNarrowVertical = 26
; HatchStyleNarrowHorizontal = 27
; HatchStyleDarkVertical = 28
; HatchStyleDarkHorizontal = 29
; HatchStyleDashedDownwardDiagonal = 30
; HatchStyleDashedUpwardDiagonal = 31
; HatchStyleDashedHorizontal = 32
; HatchStyleDashedVertical = 33
; HatchStyleSmallConfetti = 34
; HatchStyleLargeConfetti = 35
; HatchStyleZigZag = 36
; HatchStyleWave = 37
; HatchStyleDiagonalBrick = 38
; HatchStyleHorizontalBrick = 39
; HatchStyleWeave = 40
; HatchStylePlaid = 41
; HatchStyleDivot = 42
; HatchStyleDottedGrid = 43
; HatchStyleDottedDiamond = 44
; HatchStyleShingle = 45
; HatchStyleTrellis = 46
; HatchStyleSphere = 47
; HatchStyleSmallGrid = 48
; HatchStyleSmallCheckerBoard = 49
; HatchStyleLargeCheckerBoard = 50
; HatchStyleOutlinedDiamond = 51
; HatchStyleSolidDiamond = 52
; HatchStyleTotal = 53
Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0)
{
	DllCall(&quot;gdiplus\GdipCreateHatchBrush&quot;, &quot;int&quot;, HatchStyle, &quot;UInt&quot;, ARGBfront, &quot;UInt&quot;, ARGBback, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pBrush)
	return pBrush
}

;#####################################################################################

Gdip_CreateTextureBrush(pBitmap, WrapMode=1, x=0, y=0, w=&quot;&quot;, h=&quot;&quot;)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	, PtrA := A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;
	
	if !(w &amp;&amp; h)
		DllCall(&quot;gdiplus\GdipCreateTexture&quot;, Ptr, pBitmap, &quot;int&quot;, WrapMode, PtrA, pBrush)
	else
		DllCall(&quot;gdiplus\GdipCreateTexture2&quot;, Ptr, pBitmap, &quot;int&quot;, WrapMode, &quot;float&quot;, x, &quot;float&quot;, y, &quot;float&quot;, w, &quot;float&quot;, h, PtrA, pBrush)
	return pBrush
}

;#####################################################################################

; WrapModeTile = 0
; WrapModeTileFlipX = 1
; WrapModeTileFlipY = 2
; WrapModeTileFlipXY = 3
; WrapModeClamp = 4
Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode=1)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	CreatePointF(PointF1, x1, y1), CreatePointF(PointF2, x2, y2)
	DllCall(&quot;gdiplus\GdipCreateLineBrush&quot;, Ptr, &amp;PointF1, Ptr, &amp;PointF2, &quot;Uint&quot;, ARGB1, &quot;Uint&quot;, ARGB2, &quot;int&quot;, WrapMode, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, LGpBrush)
	return LGpBrush
}

;#####################################################################################

; LinearGradientModeHorizontal = 0
; LinearGradientModeVertical = 1
; LinearGradientModeForwardDiagonal = 2
; LinearGradientModeBackwardDiagonal = 3
Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode=1, WrapMode=1)
{
	CreateRectF(RectF, x, y, w, h)
	DllCall(&quot;gdiplus\GdipCreateLineBrushFromRect&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, &amp;RectF, &quot;int&quot;, ARGB1, &quot;int&quot;, ARGB2, &quot;int&quot;, LinearGradientMode, &quot;int&quot;, WrapMode, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, LGpBrush)
	return LGpBrush
}

;#####################################################################################

Gdip_CloneBrush(pBrush)
{
	DllCall(&quot;gdiplus\GdipCloneBrush&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBrush, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, pBrushClone)
	return pBrushClone
}

;#####################################################################################
; Delete resources
;#####################################################################################

Gdip_DeletePen(pPen)
{
   return DllCall(&quot;gdiplus\GdipDeletePen&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pPen)
}

;#####################################################################################

Gdip_DeleteBrush(pBrush)
{
   return DllCall(&quot;gdiplus\GdipDeleteBrush&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBrush)
}

;#####################################################################################

Gdip_DisposeImage(pBitmap)
{
   return DllCall(&quot;gdiplus\GdipDisposeImage&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap)
}

;#####################################################################################

Gdip_DeleteGraphics(pGraphics)
{
   return DllCall(&quot;gdiplus\GdipDeleteGraphics&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics)
}

;#####################################################################################

Gdip_DisposeImageAttributes(ImageAttr)
{
	return DllCall(&quot;gdiplus\GdipDisposeImageAttributes&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, ImageAttr)
}

;#####################################################################################

Gdip_DeleteFont(hFont)
{
   return DllCall(&quot;gdiplus\GdipDeleteFont&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hFont)
}

;#####################################################################################

Gdip_DeleteStringFormat(hFormat)
{
   return DllCall(&quot;gdiplus\GdipDeleteStringFormat&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hFormat)
}

;#####################################################################################

Gdip_DeleteFontFamily(hFamily)
{
   return DllCall(&quot;gdiplus\GdipDeleteFontFamily&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hFamily)
}

;#####################################################################################

Gdip_DeleteMatrix(Matrix)
{
   return DllCall(&quot;gdiplus\GdipDeleteMatrix&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, Matrix)
}

;#####################################################################################
; Text functions
;#####################################################################################

Gdip_TextToGraphics(pGraphics, Text, Options, Font=&quot;Arial&quot;, Width=&quot;&quot;, Height=&quot;&quot;, Measure=0)
{
	IWidth := Width, IHeight:= Height
	
	RegExMatch(Options, &quot;i)X([\-\d\.]+)(p*)&quot;, xpos)
	RegExMatch(Options, &quot;i)Y([\-\d\.]+)(p*)&quot;, ypos)
	RegExMatch(Options, &quot;i)W([\-\d\.]+)(p*)&quot;, Width)
	RegExMatch(Options, &quot;i)H([\-\d\.]+)(p*)&quot;, Height)
	RegExMatch(Options, &quot;i)C(?!(entre|enter))([a-f\d]+)&quot;, Colour)
	RegExMatch(Options, &quot;i)Top|Up|Bottom|Down|vCentre|vCenter&quot;, vPos)
	RegExMatch(Options, &quot;i)NoWrap&quot;, NoWrap)
	RegExMatch(Options, &quot;i)R(\d)&quot;, Rendering)
	RegExMatch(Options, &quot;i)S(\d+)(p*)&quot;, Size)

	if !Gdip_DeleteBrush(Gdip_CloneBrush(Colour2))
		PassBrush := 1, pBrush := Colour2
	
	if !(IWidth &amp;&amp; IHeight) &amp;&amp; (xpos2 || ypos2 || Width2 || Height2 || Size2)
		return -1

	Style := 0, Styles := &quot;Regular|Bold|Italic|BoldItalic|Underline|Strikeout&quot;
	Loop, Parse, Styles, |
	{
		if RegExMatch(Options, &quot;\b&quot; A_loopField)
		Style |= (A_LoopField != &quot;StrikeOut&quot;) ? (A_Index-1) : 8
	}
  
	Align := 0, Alignments := &quot;Near|Left|Centre|Center|Far|Right&quot;
	Loop, Parse, Alignments, |
	{
		if RegExMatch(Options, &quot;\b&quot; A_loopField)
			Align |= A_Index//2.1      ; 0|0|1|1|2|2
	}

	xpos := (xpos1 != &quot;&quot;) ? xpos2 ? IWidth*(xpos1/100) : xpos1 : 0
	ypos := (ypos1 != &quot;&quot;) ? ypos2 ? IHeight*(ypos1/100) : ypos1 : 0
	Width := Width1 ? Width2 ? IWidth*(Width1/100) : Width1 : IWidth
	Height := Height1 ? Height2 ? IHeight*(Height1/100) : Height1 : IHeight
	if !PassBrush
		Colour := &quot;0x&quot; (Colour2 ? Colour2 : &quot;ff000000&quot;)
	Rendering := ((Rendering1 &gt;= 0) &amp;&amp; (Rendering1 &lt;= 5)) ? Rendering1 : 4
	Size := (Size1 &gt; 0) ? Size2 ? IHeight*(Size1/100) : Size1 : 12

	hFamily := Gdip_FontFamilyCreate(Font)
	hFont := Gdip_FontCreate(hFamily, Size, Style)
	FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
	hFormat := Gdip_StringFormatCreate(FormatStyle)
	pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour)
	if !(hFamily &amp;&amp; hFont &amp;&amp; hFormat &amp;&amp; pBrush &amp;&amp; pGraphics)
		return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0
   
	CreateRectF(RC, xpos, ypos, Width, Height)
	Gdip_SetStringFormatAlign(hFormat, Align)
	Gdip_SetTextRenderingHint(pGraphics, Rendering)
	ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)

	if vPos
	{
		StringSplit, ReturnRC, ReturnRC, |
		
		if (vPos = &quot;vCentre&quot;) || (vPos = &quot;vCenter&quot;)
			ypos += (Height-ReturnRC4)//2
		else if (vPos = &quot;Top&quot;) || (vPos = &quot;Up&quot;)
			ypos := 0
		else if (vPos = &quot;Bottom&quot;) || (vPos = &quot;Down&quot;)
			ypos := Height-ReturnRC4
		
		CreateRectF(RC, xpos, ypos, Width, ReturnRC4)
		ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)
	}

	if !Measure
		E := Gdip_DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)

	if !PassBrush
		Gdip_DeleteBrush(pBrush)
	Gdip_DeleteStringFormat(hFormat)   
	Gdip_DeleteFont(hFont)
	Gdip_DeleteFontFamily(hFamily)
	return E ? E : ReturnRC
}

;#####################################################################################

Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	if (!A_IsUnicode)
	{
		nSize := DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;sString, &quot;int&quot;, -1, Ptr, 0, &quot;int&quot;, 0)
		VarSetCapacity(wString, nSize*2)
		DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;sString, &quot;int&quot;, -1, Ptr, &amp;wString, &quot;int&quot;, nSize)
	}
	
	return DllCall(&quot;gdiplus\GdipDrawString&quot;
					, Ptr, pGraphics
					, Ptr, A_IsUnicode ? &amp;sString : &amp;wString
					, &quot;int&quot;, -1
					, Ptr, hFont
					, Ptr, &amp;RectF
					, Ptr, hFormat
					, Ptr, pBrush)
}

;#####################################################################################

Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	VarSetCapacity(RC, 16)
	if !A_IsUnicode
	{
		nSize := DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;sString, &quot;int&quot;, -1, &quot;uint&quot;, 0, &quot;int&quot;, 0)
		VarSetCapacity(wString, nSize*2)   
		DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;sString, &quot;int&quot;, -1, Ptr, &amp;wString, &quot;int&quot;, nSize)
	}
	
	DllCall(&quot;gdiplus\GdipMeasureString&quot;
					, Ptr, pGraphics
					, Ptr, A_IsUnicode ? &amp;sString : &amp;wString
					, &quot;int&quot;, -1
					, Ptr, hFont
					, Ptr, &amp;RectF
					, Ptr, hFormat
					, Ptr, &amp;RC
					, &quot;uint*&quot;, Chars
					, &quot;uint*&quot;, Lines)
	
	return &amp;RC ? NumGet(RC, 0, &quot;float&quot;) &quot;|&quot; NumGet(RC, 4, &quot;float&quot;) &quot;|&quot; NumGet(RC, 8, &quot;float&quot;) &quot;|&quot; NumGet(RC, 12, &quot;float&quot;) &quot;|&quot; Chars &quot;|&quot; Lines : 0
}

; Near = 0
; Center = 1
; Far = 2
Gdip_SetStringFormatAlign(hFormat, Align)
{
   return DllCall(&quot;gdiplus\GdipSetStringFormatAlign&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hFormat, &quot;int&quot;, Align)
}

; StringFormatFlagsDirectionRightToLeft    = 0x00000001
; StringFormatFlagsDirectionVertical       = 0x00000002
; StringFormatFlagsNoFitBlackBox           = 0x00000004
; StringFormatFlagsDisplayFormatControl    = 0x00000020
; StringFormatFlagsNoFontFallback          = 0x00000400
; StringFormatFlagsMeasureTrailingSpaces   = 0x00000800
; StringFormatFlagsNoWrap                  = 0x00001000
; StringFormatFlagsLineLimit               = 0x00002000
; StringFormatFlagsNoClip                  = 0x00004000 
Gdip_StringFormatCreate(Format=0, Lang=0)
{
   DllCall(&quot;gdiplus\GdipCreateStringFormat&quot;, &quot;int&quot;, Format, &quot;int&quot;, Lang, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, hFormat)
   return hFormat
}

; Regular = 0
; Bold = 1
; Italic = 2
; BoldItalic = 3
; Underline = 4
; Strikeout = 8
Gdip_FontCreate(hFamily, Size, Style=0)
{
   DllCall(&quot;gdiplus\GdipCreateFont&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, hFamily, &quot;float&quot;, Size, &quot;int&quot;, Style, &quot;int&quot;, 0, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, hFont)
   return hFont
}

Gdip_FontFamilyCreate(Font)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	if (!A_IsUnicode)
	{
		nSize := DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;Font, &quot;int&quot;, -1, &quot;uint&quot;, 0, &quot;int&quot;, 0)
		VarSetCapacity(wFont, nSize*2)
		DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0, Ptr, &amp;Font, &quot;int&quot;, -1, Ptr, &amp;wFont, &quot;int&quot;, nSize)
	}
	
	DllCall(&quot;gdiplus\GdipCreateFontFamilyFromName&quot;
					, Ptr, A_IsUnicode ? &amp;Font : &amp;wFont
					, &quot;uint&quot;, 0
					, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, hFamily)
	
	return hFamily
}

;#####################################################################################
; Matrix functions
;#####################################################################################

Gdip_CreateAffineMatrix(m11, m12, m21, m22, x, y)
{
   DllCall(&quot;gdiplus\GdipCreateMatrix2&quot;, &quot;float&quot;, m11, &quot;float&quot;, m12, &quot;float&quot;, m21, &quot;float&quot;, m22, &quot;float&quot;, x, &quot;float&quot;, y, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, Matrix)
   return Matrix
}

Gdip_CreateMatrix()
{
   DllCall(&quot;gdiplus\GdipCreateMatrix&quot;, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, Matrix)
   return Matrix
}

;#####################################################################################
; GraphicsPath functions
;#####################################################################################

; Alternate = 0
; Winding = 1
Gdip_CreatePath(BrushMode=0)
{
	DllCall(&quot;gdiplus\GdipCreatePath&quot;, &quot;int&quot;, BrushMode, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, Path)
	return Path
}

Gdip_AddPathEllipse(Path, x, y, w, h)
{
	return DllCall(&quot;gdiplus\GdipAddPathEllipse&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, Path, &quot;float&quot;, x, &quot;float&quot;, y, &quot;float&quot;, w, &quot;float&quot;, h)
}

Gdip_AddPathPolygon(Path, Points)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	StringSplit, Points, Points, |
	VarSetCapacity(PointF, 8*Points0)   
	Loop, %Points0%
	{
		StringSplit, Coord, Points%A_Index%, `,
		NumPut(Coord1, PointF, 8*(A_Index-1), &quot;float&quot;), NumPut(Coord2, PointF, (8*(A_Index-1))+4, &quot;float&quot;)
	}   

	return DllCall(&quot;gdiplus\GdipAddPathPolygon&quot;, Ptr, Path, Ptr, &amp;PointF, &quot;int&quot;, Points0)
}

Gdip_DeletePath(Path)
{
	return DllCall(&quot;gdiplus\GdipDeletePath&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, Path)
}

;#####################################################################################
; Quality functions
;#####################################################################################

; SystemDefault = 0
; SingleBitPerPixelGridFit = 1
; SingleBitPerPixel = 2
; AntiAliasGridFit = 3
; AntiAlias = 4
Gdip_SetTextRenderingHint(pGraphics, RenderingHint)
{
	return DllCall(&quot;gdiplus\GdipSetTextRenderingHint&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;int&quot;, RenderingHint)
}

; Default = 0
; LowQuality = 1
; HighQuality = 2
; Bilinear = 3
; Bicubic = 4
; NearestNeighbor = 5
; HighQualityBilinear = 6
; HighQualityBicubic = 7
Gdip_SetInterpolationMode(pGraphics, InterpolationMode)
{
   return DllCall(&quot;gdiplus\GdipSetInterpolationMode&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;int&quot;, InterpolationMode)
}

; Default = 0
; HighSpeed = 1
; HighQuality = 2
; None = 3
; AntiAlias = 4
Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
{
   return DllCall(&quot;gdiplus\GdipSetSmoothingMode&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;int&quot;, SmoothingMode)
}

; CompositingModeSourceOver = 0 (blended)
; CompositingModeSourceCopy = 1 (overwrite)
Gdip_SetCompositingMode(pGraphics, CompositingMode=0)
{
   return DllCall(&quot;gdiplus\GdipSetCompositingMode&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;int&quot;, CompositingMode)
}

;#####################################################################################
; Extra functions
;#####################################################################################

Gdip_Startup()
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	if !DllCall(&quot;GetModuleHandle&quot;, &quot;str&quot;, &quot;gdiplus&quot;, Ptr)
		DllCall(&quot;LoadLibrary&quot;, &quot;str&quot;, &quot;gdiplus&quot;)
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
	DllCall(&quot;gdiplus\GdiplusStartup&quot;, A_PtrSize ? &quot;UPtr*&quot; : &quot;uint*&quot;, pToken, Ptr, &amp;si, Ptr, 0)
	return pToken
}

Gdip_Shutdown(pToken)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	DllCall(&quot;gdiplus\GdiplusShutdown&quot;, Ptr, pToken)
	if hModule := DllCall(&quot;GetModuleHandle&quot;, &quot;str&quot;, &quot;gdiplus&quot;, Ptr)
		DllCall(&quot;FreeLibrary&quot;, Ptr, hModule)
	return 0
}

; Prepend = 0; The new operation is applied before the old operation.
; Append = 1; The new operation is applied after the old operation.
Gdip_RotateWorldTransform(pGraphics, Angle, MatrixOrder=0)
{
	return DllCall(&quot;gdiplus\GdipRotateWorldTransform&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;float&quot;, Angle, &quot;int&quot;, MatrixOrder)
}

Gdip_ScaleWorldTransform(pGraphics, x, y, MatrixOrder=0)
{
	return DllCall(&quot;gdiplus\GdipScaleWorldTransform&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;float&quot;, x, &quot;float&quot;, y, &quot;int&quot;, MatrixOrder)
}

Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder=0)
{
	return DllCall(&quot;gdiplus\GdipTranslateWorldTransform&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;float&quot;, x, &quot;float&quot;, y, &quot;int&quot;, MatrixOrder)
}

Gdip_ResetWorldTransform(pGraphics)
{
	return DllCall(&quot;gdiplus\GdipResetWorldTransform&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics)
}

Gdip_GetRotatedTranslation(Width, Height, Angle, ByRef xTranslation, ByRef yTranslation)
{
	pi := 3.14159, TAngle := Angle*(pi/180)	

	Bound := (Angle &gt;= 0) ? Mod(Angle, 360) : 360-Mod(-Angle, -360)
	if ((Bound &gt;= 0) &amp;&amp; (Bound &lt;= 90))
		xTranslation := Height*Sin(TAngle), yTranslation := 0
	else if ((Bound &gt; 90) &amp;&amp; (Bound &lt;= 180))
		xTranslation := (Height*Sin(TAngle))-(Width*Cos(TAngle)), yTranslation := -Height*Cos(TAngle)
	else if ((Bound &gt; 180) &amp;&amp; (Bound &lt;= 270))
		xTranslation := -(Width*Cos(TAngle)), yTranslation := -(Height*Cos(TAngle))-(Width*Sin(TAngle))
	else if ((Bound &gt; 270) &amp;&amp; (Bound &lt;= 360))
		xTranslation := 0, yTranslation := -Width*Sin(TAngle)
}

Gdip_GetRotatedDimensions(Width, Height, Angle, ByRef RWidth, ByRef RHeight)
{
	pi := 3.14159, TAngle := Angle*(pi/180)
	if !(Width &amp;&amp; Height)
		return -1
	RWidth := Ceil(Abs(Width*Cos(TAngle))+Abs(Height*Sin(TAngle)))
	RHeight := Ceil(Abs(Width*Sin(TAngle))+Abs(Height*Cos(Tangle)))
}

; RotateNoneFlipNone   = 0
; Rotate90FlipNone     = 1
; Rotate180FlipNone    = 2
; Rotate270FlipNone    = 3
; RotateNoneFlipX      = 4
; Rotate90FlipX        = 5
; Rotate180FlipX       = 6
; Rotate270FlipX       = 7
; RotateNoneFlipY      = Rotate180FlipX
; Rotate90FlipY        = Rotate270FlipX
; Rotate180FlipY       = RotateNoneFlipX
; Rotate270FlipY       = Rotate90FlipX
; RotateNoneFlipXY     = Rotate180FlipNone
; Rotate90FlipXY       = Rotate270FlipNone
; Rotate180FlipXY      = RotateNoneFlipNone
; Rotate270FlipXY      = Rotate90FlipNone 

Gdip_ImageRotateFlip(pBitmap, RotateFlipType=1)
{
	return DllCall(&quot;gdiplus\GdipImageRotateFlip&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pBitmap, &quot;int&quot;, RotateFlipType)
}

; Replace = 0
; Intersect = 1
; Union = 2
; Xor = 3
; Exclude = 4
; Complement = 5
Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0)
{
   return DllCall(&quot;gdiplus\GdipSetClipRect&quot;,  A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;float&quot;, x, &quot;float&quot;, y, &quot;float&quot;, w, &quot;float&quot;, h, &quot;int&quot;, CombineMode)
}

Gdip_SetClipPath(pGraphics, Path, CombineMode=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	return DllCall(&quot;gdiplus\GdipSetClipPath&quot;, Ptr, pGraphics, Ptr, Path, &quot;int&quot;, CombineMode)
}

Gdip_ResetClip(pGraphics)
{
   return DllCall(&quot;gdiplus\GdipResetClip&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics)
}

Gdip_GetClipRegion(pGraphics)
{
	Region := Gdip_CreateRegion()
	DllCall(&quot;gdiplus\GdipGetClip&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, pGraphics, &quot;UInt*&quot;, Region)
	return Region
}

Gdip_SetClipRegion(pGraphics, Region, CombineMode=0)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;gdiplus\GdipSetClipRegion&quot;, Ptr, pGraphics, Ptr, Region, &quot;int&quot;, CombineMode)
}

Gdip_CreateRegion()
{
	DllCall(&quot;gdiplus\GdipCreateRegion&quot;, &quot;UInt*&quot;, Region)
	return Region
}

Gdip_DeleteRegion(Region)
{
	return DllCall(&quot;gdiplus\GdipDeleteRegion&quot;, A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;, Region)
}

;#####################################################################################
; BitmapLockBits
;#####################################################################################

Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode = 3, PixelFormat = 0x26200a)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	CreateRect(Rect, x, y, w, h)
	VarSetCapacity(BitmapData, 16+2*(A_PtrSize ? A_PtrSize : 4), 0)
	E := DllCall(&quot;Gdiplus\GdipBitmapLockBits&quot;, Ptr, pBitmap, Ptr, &amp;Rect, &quot;uint&quot;, LockMode, &quot;int&quot;, PixelFormat, Ptr, &amp;BitmapData)
	Stride := NumGet(BitmapData, 8, &quot;Int&quot;)
	Scan0 := NumGet(BitmapData, 16, Ptr)
	return E
}

;#####################################################################################

Gdip_UnlockBits(pBitmap, ByRef BitmapData)
{
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	return DllCall(&quot;Gdiplus\GdipBitmapUnlockBits&quot;, Ptr, pBitmap, Ptr, &amp;BitmapData)
}

;#####################################################################################

Gdip_SetLockBitPixel(ARGB, Scan0, x, y, Stride)
{
	Numput(ARGB, Scan0+0, (x*4)+(y*Stride), &quot;UInt&quot;)
}

;#####################################################################################

Gdip_GetLockBitPixel(Scan0, x, y, Stride)
{
	return NumGet(Scan0+0, (x*4)+(y*Stride), &quot;UInt&quot;)
}

;#####################################################################################

Gdip_PixelateBitmap(pBitmap, ByRef pBitmapOut, BlockSize)
{
	static PixelateBitmap
	
	Ptr := A_PtrSize ? &quot;UPtr&quot; : &quot;UInt&quot;
	
	if (!PixelateBitmap)
	{
		if A_PtrSize != 8 ; x86 machine code
		MCode_PixelateBitmap =
		(LTrim Join
		558BEC83EC3C8B4514538B5D1C99F7FB56578BC88955EC894DD885C90F8E830200008B451099F7FB8365DC008365E000894DC88955F08945E833FF897DD4
		397DE80F8E160100008BCB0FAFCB894DCC33C08945F88945FC89451C8945143BD87E608B45088D50028BC82BCA8BF02BF2418945F48B45E02955F4894DC4
		8D0CB80FAFCB03CA895DD08BD1895DE40FB64416030145140FB60201451C8B45C40FB604100145FC8B45F40FB604020145F883C204FF4DE475D6034D18FF
		4DD075C98B4DCC8B451499F7F98945148B451C99F7F989451C8B45FC99F7F98945FC8B45F899F7F98945F885DB7E648B450C8D50028BC82BCA83C103894D
		C48BC82BCA41894DF48B4DD48945E48B45E02955E48D0C880FAFCB03CA895DD08BD18BF38A45148B7DC48804178A451C8B7DF488028A45FC8804178A45F8
		8B7DE488043A83C2044E75DA034D18FF4DD075CE8B4DCC8B7DD447897DD43B7DE80F8CF2FEFFFF837DF0000F842C01000033C08945F88945FC89451C8945
		148945E43BD87E65837DF0007E578B4DDC034DE48B75E80FAF4D180FAFF38B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945CC0F
		B6440E030145140FB60101451C0FB6440F010145FC8B45F40FB604010145F883C104FF4DCC75D8FF45E4395DE47C9B8B4DF00FAFCB85C9740B8B451499F7
		F9894514EB048365140033F63BCE740B8B451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB
		038975F88975E43BDE7E5A837DF0007E4C8B4DDC034DE48B75E80FAF4D180FAFF38B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955CC8A55
		1488540E038A551C88118A55FC88540F018A55F888140183C104FF4DCC75DFFF45E4395DE47CA68B45180145E0015DDCFF4DC80F8594FDFFFF8B451099F7
		FB8955F08945E885C00F8E450100008B45EC0FAFC38365DC008945D48B45E88945CC33C08945F88945FC89451C8945148945103945EC7E6085DB7E518B4D
		D88B45080FAFCB034D108D50020FAF4D18034DDC8BF08BF88945F403CA2BF22BFA2955F4895DC80FB6440E030145140FB60101451C0FB6440F010145FC8B
		45F40FB604080145F883C104FF4DC875D8FF45108B45103B45EC7CA08B4DD485C9740B8B451499F7F9894514EB048365140033F63BCE740B8B451C99F7F9
		89451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975103975EC7E5585DB7E468B4DD88B450C
		0FAFCB034D108D50020FAF4D18034DDC8BF08BF803CA2BF22BFA2BC2895DC88A551488540E038A551C88118A55FC88540F018A55F888140183C104FF4DC8
		75DFFF45108B45103B45EC7CAB8BC3C1E0020145DCFF4DCC0F85CEFEFFFF8B4DEC33C08945F88945FC89451C8945148945103BC87E6C3945F07E5C8B4DD8
		8B75E80FAFCB034D100FAFF30FAF4D188B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945C80FB6440E030145140FB60101451C0F
		B6440F010145FC8B45F40FB604010145F883C104FF4DC875D833C0FF45108B4DEC394D107C940FAF4DF03BC874068B451499F7F933F68945143BCE740B8B
		451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975083975EC7E63EB0233F639
		75F07E4F8B4DD88B75E80FAFCB034D080FAFF30FAF4D188B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955108A551488540E038A551C8811
		8A55FC88540F018A55F888140883C104FF4D1075DFFF45088B45083B45EC7C9F5F5E33C05BC9C21800
		)
		else ; x64 machine code
		MCode_PixelateBitmap =
		(LTrim Join
		4489442418488954241048894C24085355565741544155415641574883EC28418BC1448B8C24980000004C8BDA99488BD941F7F9448BD0448BFA8954240C
		448994248800000085C00F8E9D020000418BC04533E4458BF299448924244C8954241041F7F933C9898C24980000008BEA89542404448BE889442408EB05
		4C8B5C24784585ED0F8E1A010000458BF1418BFD48897C2418450FAFF14533D233F633ED4533E44533ED4585C97E5B4C63BC2490000000418D040A410FAF
		C148984C8D441802498BD9498BD04D8BD90FB642010FB64AFF4403E80FB60203E90FB64AFE4883C2044403E003F149FFCB75DE4D03C748FFCB75D0488B7C
		24188B8C24980000004C8B5C2478418BC59941F7FE448BE8418BC49941F7FE448BE08BC59941F7FE8BE88BC69941F7FE8BF04585C97E4048639C24900000
		004103CA4D8BC1410FAFC94863C94A8D541902488BCA498BC144886901448821408869FF408871FE4883C10448FFC875E84803D349FFC875DA8B8C249800
		0000488B5C24704C8B5C24784183C20448FFCF48897C24180F850AFFFFFF8B6C2404448B2424448B6C24084C8B74241085ED0F840A01000033FF33DB4533
		DB4533D24533C04585C97E53488B74247085ED7E42438D0C04418BC50FAF8C2490000000410FAFC18D04814863C8488D5431028BCD0FB642014403D00FB6
		024883C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC17CB28BCD410FAFC985C9740A418BC299F7F98BF0EB0233F685C9740B418BC3
		99F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585C97E4D4C8B74247885ED7E3841
		8D0C14418BC50FAF8C2490000000410FAFC18D04814863C84A8D4431028BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2413BD17CBD
		4C8B7424108B8C2498000000038C2490000000488B5C24704503E149FFCE44892424898C24980000004C897424100F859EFDFFFF448B7C240C448B842480
		000000418BC09941F7F98BE8448BEA89942498000000896C240C85C00F8E3B010000448BAC2488000000418BCF448BF5410FAFC9898C248000000033FF33
		ED33F64533DB4533D24533C04585FF7E524585C97E40418BC5410FAFC14103C00FAF84249000000003C74898488D541802498BD90FB642014403D00FB602
		4883C2044403D80FB642FB03F00FB642FA03E848FFCB75DE488B5C247041FFC0453BC77CAE85C9740B418BC299F7F9448BE0EB034533E485C9740A418BC3
		99F7F98BD8EB0233DB85C9740A8BC699F7F9448BD8EB034533DB85C9740A8BC599F7F9448BD0EB034533D24533C04585FF7E4E488B4C24784585C97E3541
		8BC5410FAFC14103C00FAF84249000000003C74898488D540802498BC144886201881A44885AFF448852FE4883C20448FFC875E941FFC0453BC77CBE8B8C
		2480000000488B5C2470418BC1C1E00203F849FFCE0F85ECFEFFFF448BAC24980000008B6C240C448BA4248800000033FF33DB4533DB4533D24533C04585
		FF7E5A488B7424704585ED7E48418BCC8BC5410FAFC94103C80FAF8C2490000000410FAFC18D04814863C8488D543102418BCD0FB642014403D00FB60248
		83C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC77CAB418BCF410FAFCD85C9740A418BC299F7F98BF0EB0233F685C9740B418BC399
		F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585FF7E4E4585ED7E42418BCC8BC541
		0FAFC903CA0FAF8C2490000000410FAFC18D04814863C8488B442478488D440102418BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2
		413BD77CB233C04883C428415F415E415D415C5F5E5D5BC3
		)
		
		VarSetCapacity(PixelateBitmap, StrLen(MCode_PixelateBitmap)//2)
		Loop % StrLen(MCode_PixelateBitmap)//2		;%
			NumPut(&quot;0x&quot; SubStr(MCode_PixelateBitmap, (2*A_Index)-1, 2), PixelateBitmap, A_Index-1, &quot;UChar&quot;)
		DllCall(&quot;VirtualProtect&quot;, Ptr, &amp;PixelateBitmap, Ptr, VarSetCapacity(PixelateBitmap), &quot;uint&quot;, 0x40, A_PtrSize ? &quot;UPtr*&quot; : &quot;UInt*&quot;, 0)
	}

	Gdip_GetImageDimensions(pBitmap, Width, Height)
	
	if (Width != Gdip_GetImageWidth(pBitmapOut) || Height != Gdip_GetImageHeight(pBitmapOut))
		return -1
	if (BlockSize &gt; Width || BlockSize &gt; Height)
		return -2

	E1 := Gdip_LockBits(pBitmap, 0, 0, Width, Height, Stride1, Scan01, BitmapData1)
	E2 := Gdip_LockBits(pBitmapOut, 0, 0, Width, Height, Stride2, Scan02, BitmapData2)
	if (E1 || E2)
		return -3

	E := DllCall(&amp;PixelateBitmap, Ptr, Scan01, Ptr, Scan02, &quot;int&quot;, Width, &quot;int&quot;, Height, &quot;int&quot;, Stride1, &quot;int&quot;, BlockSize)
	
	Gdip_UnlockBits(pBitmap, BitmapData1), Gdip_UnlockBits(pBitmapOut, BitmapData2)
	return 0
}

;#####################################################################################

Gdip_ToARGB(A, R, G, B)
{
	return (A &lt;&lt; 24) | (R &lt;&lt; 16) | (G &lt;&lt; 8) | B
}

;#####################################################################################

Gdip_FromARGB(ARGB, ByRef A, ByRef R, ByRef G, ByRef B)
{
	A := (0xff000000 &amp; ARGB) &gt;&gt; 24
	R := (0x00ff0000 &amp; ARGB) &gt;&gt; 16
	G := (0x0000ff00 &amp; ARGB) &gt;&gt; 8
	B := 0x000000ff &amp; ARGB
}

;#####################################################################################

Gdip_AFromARGB(ARGB)
{
	return (0xff000000 &amp; ARGB) &gt;&gt; 24
}

;#####################################################################################

Gdip_RFromARGB(ARGB)
{
	return (0x00ff0000 &amp; ARGB) &gt;&gt; 16
}

;#####################################################################################

Gdip_GFromARGB(ARGB)
{
	return (0x0000ff00 &amp; ARGB) &gt;&gt; 8
}

;#####################################################################################

Gdip_BFromARGB(ARGB)
{
	return 0x000000ff &amp; ARGB
}

;#####################################################################################

StrGetB(Address, Length=-1, Encoding=0)
{
	; Flexible parameter handling:
	if Length is not integer
	Encoding := Length,  Length := -1

	; Check for obvious errors.
	if (Address+0 &lt; 1024)
		return

	; Ensure &#039;Encoding&#039; contains a numeric identifier.
	if Encoding = UTF-16
		Encoding = 1200
	else if Encoding = UTF-8
		Encoding = 65001
	else if SubStr(Encoding,1,2)=&quot;CP&quot;
		Encoding := SubStr(Encoding,3)

	if !Encoding ; &quot;&quot; or 0
	{
		; No conversion necessary, but we might not want the whole string.
		if (Length == -1)
			Length := DllCall(&quot;lstrlen&quot;, &quot;uint&quot;, Address)
		VarSetCapacity(String, Length)
		DllCall(&quot;lstrcpyn&quot;, &quot;str&quot;, String, &quot;uint&quot;, Address, &quot;int&quot;, Length + 1)
	}
	else if Encoding = 1200 ; UTF-16
	{
		char_count := DllCall(&quot;WideCharToMultiByte&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0x400, &quot;uint&quot;, Address, &quot;int&quot;, Length, &quot;uint&quot;, 0, &quot;uint&quot;, 0, &quot;uint&quot;, 0, &quot;uint&quot;, 0)
		VarSetCapacity(String, char_count)
		DllCall(&quot;WideCharToMultiByte&quot;, &quot;uint&quot;, 0, &quot;uint&quot;, 0x400, &quot;uint&quot;, Address, &quot;int&quot;, Length, &quot;str&quot;, String, &quot;int&quot;, char_count, &quot;uint&quot;, 0, &quot;uint&quot;, 0)
	}
	else if Encoding is integer
	{
		; Convert from target encoding to UTF-16 then to the active code page.
		char_count := DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, Encoding, &quot;uint&quot;, 0, &quot;uint&quot;, Address, &quot;int&quot;, Length, &quot;uint&quot;, 0, &quot;int&quot;, 0)
		VarSetCapacity(String, char_count * 2)
		char_count := DllCall(&quot;MultiByteToWideChar&quot;, &quot;uint&quot;, Encoding, &quot;uint&quot;, 0, &quot;uint&quot;, Address, &quot;int&quot;, Length, &quot;uint&quot;, &amp;String, &quot;int&quot;, char_count * 2)
		String := StrGetB(&amp;String, char_count, 1200)
	}
	
	return String
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Fri, 09 Oct 2020 04:05:02 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142572#p142572</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142571#p142571</link>
			<description><![CDATA[<div class="quotebox"><cite>Malcev пишет:</cite><blockquote><p>Если у вас монитор работает с 60 Hz Refresh rate, то в идеале вам проходить цикл поиска в 900 повторов за 15 секунд.</p></blockquote></div><p>С командой &quot;setbatchlines -1&quot; + той формулой движения + поиском и без &quot;setmousedelay -1&quot;, получилось <strong>21сек</strong> за <strong>840</strong> повторов.</p>]]></description>
			<author><![CDATA[null@example.com (Botsy)]]></author>
			<pubDate>Thu, 08 Oct 2020 20:54:07 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142571#p142571</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142570#p142570</link>
			<description><![CDATA[<p>Если у вас монитор работает с 60 Hz Refresh rate, то в идеале вам проходить цикл поиска в 900 повторов за 15 секунд.</p>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Thu, 08 Oct 2020 20:28:16 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142570#p142570</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142569#p142569</link>
			<description><![CDATA[<p><strong>Malcev</strong> обалдеть, вот это скорость ! Я и не знал про эти команды.<br /></p><div class="codebox"><pre><code>
setbatchlines -1
setmousedelay -1
</code></pre></div><p>Один только &quot;setbatchlines&quot; увеличил производительность в 2 раза. Вторая команда вообще супер для семейства стандартных &quot;mousemove&quot;, правда я использую отдельную библиотеку для эмуляции, там это работать не будет, но все равно, в 2 раза стало быстрее. Спасибо ! )</p>]]></description>
			<author><![CDATA[null@example.com (Botsy)]]></author>
			<pubDate>Thu, 08 Oct 2020 20:09:52 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142569#p142569</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: поиск картинки одновременно с движением мышки]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=142568#p142568</link>
			<description><![CDATA[<div class="codebox"><pre><code>setbatchlines -1
setmousedelay -1
a := a_tickcount
loop 450
{
   MouseMove, 0, 0, 0
   MouseMove, 500, 500, 0
}
msgbox % a_tickcount - a</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Thu, 08 Oct 2020 20:04:24 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=142568#p142568</guid>
		</item>
	</channel>
</rss>
