First of all, this will only work in games that allows Windowed Mode or Windowed (No border) Mode. Do not forget to save your project often in any case of unwanted situations. Let's Start!
-Step 1: The Basic-
Step 1:
Once your project is open, click on "Project" then "Add Windows Form". Give it a name and press "Add".
Step 2:
Click on "Project" then "Add Module". Name it "Overlay" then click "Add"
Step 3:
Double click on your Overlay Module and replace all code with this one (Base off the code by Stefsot)
Code:
Imports System.Runtime.InteropServices
Imports System.Net.Mail
Imports System.Text
Public Module Overlay
Public Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
Public window_loc As RECT
Public screencenter(1) As Integer
<DllImport("user32.dll")> _
Public Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
End Function
<DllImportAttribute("kernel32.dll", EntryPoint:="ReadProcessMemory", SetLastError:=True)> _
Private Function ReadProcessMemory(<InAttribute()> ByVal hProcess As System.IntPtr, <InAttribute()> ByVal lpBaseAddress As System.IntPtr, <Out()> ByVal lpBuffer As Byte(), ByVal nSize As UInteger, <OutAttribute()> ByRef lpNumberOfBytesRead As UInteger) As <System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)> Boolean
End Function
Public Declare Function ReadProcessMemory2 Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Long, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal Classname As String, ByVal WindowName As String) As IntPtr
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As Integer) As IntPtr
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As IntPtr) As Integer
Public Const PROCESS_VM_ALL As Integer = &H1F0FFF
Public hWnd As IntPtr, pHandle As IntPtr, processID As Integer
Const ProcessName As String = "iw6mp64_ship"
Function load_()
Dim proc As Process() = Process.GetProcessesByName(ProcessName)
Dim windowname As String
windowname = proc(0).MainWindowTitle
hWnd = FindWindow(vbNullString, windowname)
GetWindowThreadProcessId(hWnd, processID)
pHandle = OpenProcess(PROCESS_VM_ALL, 0, processID)
If hWnd = 0 Then Return 0 Else Return 1
End Function
Sub is_active(Optional ByVal exit_ As Boolean = True)
Dim p As Process() = Process.GetProcessesByName(ProcessName)
If p.Length = 0 And exit_ Then
Environment.Exit(0)
End If
End Sub
Function readInt(ByVal address As Integer, ByVal bytes As Integer)
Dim read_value As Long = 0
ReadProcessMemory2(pHandle, address, read_value, bytes, 0)
Return read_value
End Function
Function readFloat(ByVal address As Integer, ByVal bytes As Integer)
Dim read_value(bytes) As Byte
ReadProcessMemory(pHandle, address, read_value, bytes, 0)
Return BitConverter.ToSingle(read_value, 0)
End Function
Function readString(ByVal address As Integer, ByVal bytes As Integer, ByVal terminator As Byte)
Dim read_value As String = ""
Dim buffer As Byte
For i = 0 To bytes
ReadProcessMemory2(pHandle, address + i, buffer, 1, 0)
If Not buffer = terminator Then
read_value &= Chr(buffer)
Else
Exit For
End If
Next
Return read_value
End Function
End Module
Replace iw6mp64_ship at the line Const ProcessName As String = "iw6mp64_ship" by another process name if you wish to use it with a different game.
-Chapter 2: The Form Editing-
In this chapter, we will editing the newly created form to make it invisible and make it our overlay.
Step 1:
Change the form's Back Color and Transparency Key to Black. You can find those 2 options in the form's properties located at the bottom right (By default) of Visual Studio. Make sure that the form is selected.
Step 2: Change the FormBorderStyle to None, the ShowInTaskbar to False and TopMost to True.
Step 3: Double click on the form and add this code under Public Class (Form Name) (Base off the code by Stefsot)
Code:
Public Declare Function ReadProcessMemory2 Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Long, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal Classname As String, ByVal WindowName As String) As IntPtr
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As Integer) As IntPtr
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As IntPtr) As Integer
Public Const PROCESS_VM_ALL As Integer = &H1F0FFF
Public hWnd As IntPtr, pHandle As IntPtr, processID As Integer
Const ProcessName As String = "iw6mp64_ship"
Change the process name again if you wish to use it on another game.
Step 4:
Add a Timer to your form with an Interval of 1. This timer will make sure that the form will be as big as the game's resolution and at the same location as the game. Add this code to your timer. (Base off the code by Stefsot)
Code:
Call load_()
Dim proc As Process() = Process.GetProcessesByName(ProcessName)
Dim MyHeight = Me.Height
Dim windowname As String
windowname = proc(0).MainWindowTitle
hWnd = FindWindow(vbNullString, windowname)
GetWindowThreadProcessId(hWnd, processID)
pHandle = OpenProcess(PROCESS_VM_ALL, 0, processID)
GetWindowRect(Overlay.hWnd, window_loc)
Me.Location = New Point(window_loc.Left, window_loc.Top)
Me.Size = New Point(window_loc.Right - window_loc.Left, window_loc.Bottom - window_loc.Top)
screencenter(0) = Me.Width = 100
screencenter(1) = Me.Height = 100
You can set the timer to be Enabled at all time by changing the "Enabled" properties to true but I suggest to load the form and turn on the timer when your project detects the game. This way, it will prevent crash.
All you have to do now is to add whatever you like to the form. You might need to play with the location of the items to fit well on the game's window.
Happy Editing!