While with some occasions, you have to translate some c# construct to that equivalent of native representation. this is common, an example of such conversion is when you try to convert a delegate (function/method) to a IntPtr which will be accepted by a pinovke calls.
normally you have two ways of doing such.
1. the Marshal.GetFunctionPointerForDelegate.
Let's see a code snippet. We will pass one function pionter by the address of one method to the WNDCLASSEX class.
the code snippet is as follow.
WNDCLASSEX wcx = new WNDCLASSEX();
wcx.cbSize = Marshal.SizeOf(wcx);
wcx.style = (int) (ClassStyles.VerticalRedraw | ClassStyles.HorizontalRedraw);
unsafe
{
//IntPtr address = MainWndProc; -- this is not necessary to put inside a Unsafe context
IntPtr address2 = Marshal.GetFunctionPointerForDelegate((Delegate) (WndProc) MainWndProc);
wcx.lpfnWndProc = address2;
}
A special note on the the unsafe block, it is not necessary to have the unsafe block wrapping the code.
and the MainWndProc is something like this:
static IntPtr MainWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
IntPtr hdc;
PAINTSTRUCT ps;
RECT rect;
//switch ((WM) message)
//{
// WinAPI.BeginPaint(hWnd, out ps);
// break;
//}
switch ((WM)msg)
{
case WM.PAINT:
hdc = WinAPI.BeginPaint(hWnd, out ps);
WinAPI.GetClientRect(hWnd, out rect);
WinAPI.DrawText(hdc, "Hello, Windows 98!", -1, ref rect, Win32_DT_Constant.DT_SINGLELINE | Win32_DT_Constant.DT_CENTER | Win32_DT_Constant.DT_VCENTER);
WinAPI.EndPaint(hWnd, ref ps);
return IntPtr.Zero;
break;
case WM.DESTROY:
WinAPI.PostQuitMessage(0);
return IntPtr.Zero;
break;
}
return WinAPI.DefWindowProc(hWnd, (WM)msg, wParam, lParam);
}
the definition of the Delegate WndProc is something like this:
public delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
2. Delegate.Method.MethodHandle.GetFunctionPointer();
Another way, which is less ideal is you can use the Delegate's method property and then you can further get to the MethodHandle, and the last call GetFunctionPointer().
E.g is as follow.
wndClass.lpfnWndProc = ((WndProc)((hWnd, message, wParam, lParam) =>
{
IntPtr hdc;
PAINTSTRUCT ps;
RECT rect;
//switch ((WM) message)
//{
// WinAPI.BeginPaint(hWnd, out ps);
// break;
//}
switch ((WM)message)
{
case WM.PAINT:
hdc = WinAPI.BeginPaint(hWnd, out ps);
WinAPI.GetClientRect(hWnd, out rect);
WinAPI.DrawText(hdc, "Hello, Windows 98!", -1, ref rect, Win32_DT_Constant.DT_SINGLELINE | Win32_DT_Constant.DT_CENTER | Win32_DT_Constant.DT_VCENTER);
WinAPI.EndPaint(hWnd, ref ps);
return IntPtr.Zero;
break;
case WM.DESTROY:
WinAPI.PostQuitMessage(0);
return IntPtr.Zero;
break;
}
return WinAPI.DefWindowProc(hWnd, (WM)message, wParam, lParam);
}
)).Method.MethodHandle.GetFunctionPointer();