Заметим, что он прекрасно работает и без маршалинга параметров (без атрибута перед string s). Но маршалинг уточняет, что тип LPTSTR (Unicode-совместимая версия char*), действующий в этом конкретном случае по умолчанию, должен быть приведен к типу LPSTR (обычный тип char*). Функцию puts, импортированную из msvcrt.dll, оказывается, можно переименовать (присвоить ей любое другое имя, например, Out). Это делается так:
[DllImport("msvcrt.dll", EntryPoint="puts")]
public static extern int Out (string c);
static void Main() { Out ("Remnants of COM, ah? \n\n"); }
Покажем, как программным способом (используя функции API) переместить курсор в желаемую позицию.
[DllImport("User32.dll")]
public static extern bool SetCursorPos (int x, int y);
[DllImport("User32.dll")]
public unsafe static extern bool ClientToScreen (IntPtr hWnd, POINT* lp);
Вторая функция требует подать на вход аргумент типа HWND. Запомните, что в окружении NET ему соответствует тип IntPtr. Кроме того, вторая функция требует аргумент типа POINT*, то есть адрес структуры POINT, используемой в Win32 для работы с координатами точек в пределах окна. Для импорта структуры мы можем создать ее аналог, адекватно описанный в среде .NET, например:
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x, y; // Типу LONG в Win32-окружении соответствует тип int в среде NET
};
Для того, чтобы работать с указателем на эту структуру, следует использовать спецификатор unsafe и спокойно работать с адресами, как и в проекте типа Visual C++ Win32. Свойство Handle класса Form возвращает необходимый нам описатель окна типа HWND.
public unsafe void Test() //========= API-style
{
POINT p;
p.x = p.y = 10;
ClientToScreen (Handle, &p);
SetCursorPos (p.x, p.y);
}
Следующий вариант показывает, как обойтись без структуры POINT и использовать вместо нее существующую в NET структуру Point.
public unsafe void Test() //========= Mixed-style
{
Point pt = new Point (10, 40);
ClientToScreen (Handle, (POINT*)&pt); // Необходимо привести тип
SetCursorPos (pt.X, pt.Y);
}
Так как внутри функции Testмы начинаем работать с указателями (а это опасно), то она должны быть отмечены описателем unsafe (опасная). Этого мало, весь проект нужно отметить, как опасный.
¨ Откройте Property Pages, найдите узел дерева с именем Configuration Properties4Build,
¨ Установите в True свойство Allow Unsafe Code Blocks и нажмите OK.
Наконец, покажем, как решить задачу без помощи Win32-API и обойтись только средствами NET.
public void Test() //========= Net-style. Описатель unsafe не нужен
{
Point pt = PointToScreen (new Point (10, 40));
Cursor.Position = (pt);
}
Следующий пример показывает, как импортировать API-функции CreateFontIndirect и DeleteObject и превратить их в статические методы класса Program. Кроме того, здесь показано, как импортировать Win32-структуру.
class Program
{
[StructLayout(LayoutKind.Sequential)]
public class LOGFONT
{
public const int LF_FACESIZE = 32;
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public int lfWeight;
public byte lfItalic;
public byte lfUnderline;
public byte lfStrikeOut;
public byte lfCharSet;
public byte lfOutPrecision;
public byte lfClipPrecision;
public byte lfQuality;
public byte lfPitchAndFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]
public string lfFaceName;
}
[DllImport("gdi32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr CreateFontIndirect([In, MarshalAs(UnmanagedType.LPStruct)] LOGFONT lplf);
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr handle);
public static void Main()
{
LOGFONT lf = new LOGFONT();
lf.lfHeight = 9;
lf.lfFaceName = "Arial";
IntPtr handle = CreateFontIndirect(lf);
if (IntPtr.Zero == handle)
Console.WriteLine("Can't creates a logical font.");
else
{
if (IntPtr.Size == 4)
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.