本來是想實作控制台程式運作時自動全屏,但是隻找到VC下的實作方法(http://www.vckbase.com/bbs/prime/viewprime.asp?id=347)。
其中要使用兩個未公開的Win32 API函數來存取控制台視窗,這就需要使用動态調用的方法,動态調用中使用的Windows API函數主要有三個,即:Loadlibrary,GetProcAddress和Freelibrary。步驟如下:
1. Loadlibrary: 裝載指定DLL動态庫
2. GetProcAddress:獲得函數的入口位址
3. Freelibrary: 從記憶體中解除安裝動态庫
但是C#中是沒有函數指針,無法直接使用GetProcAddress傳回的入口位址。後來找到資料,其實.NET 2.0新增了Marshal.GetDelegateForFunctionPointer 方法可以滿足這個要求,MSDN裡的解釋是:将非托管函數指針轉換為委托。
後面的事就簡單啦,我把它編成了一個類來友善調用。
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace feiyun0112.cnblogs.com
{
public class DllInvoke
{
Win API#region Win API
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(string path);
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, string funcName);
[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);
#endregion
private IntPtr hLib;
public DllInvoke(String DLLPath)
{
hLib = LoadLibrary(DLLPath);
}
~DllInvoke()
{
FreeLibrary(hLib);
}
//将要執行的函數轉換為委托
public Delegate Invoke (string APIName,Type t)
{
IntPtr api = GetProcAddress(hLib, APIName);
return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t);
}
}
}
下面是使用的例子:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using feiyun0112.cnblogs.com;
namespace ConsoleApplication1
{
class Program
{
Win API#region Win API
[DllImport("kernel32.dll")]
public static extern IntPtr GetStdHandle(int nStdHandle);
const int STD_OUTPUT_HANDLE = -11;
#endregion
public delegate bool SetConsoleDisplayMode(IntPtr hOut, int dwNewMode, out int lpdwOldMode);
static void Main(string[] args)
{
DllInvoke dll = new DllInvoke("kernel32.dll");
int dwOldMode;
//标準輸出句柄
IntPtr hOut = GetStdHandle(STD_OUTPUT_HANDLE);
//調用Win API,設定螢幕最大化
SetConsoleDisplayMode s = (SetConsoleDisplayMode)dll.Invoke("SetConsoleDisplayMode", typeof(SetConsoleDisplayMode));
s(hOut, 1, out dwOldMode);
Console.WriteLine("********************Full Screen Mode********************");
Console.ReadLine();
}
}
}