2012年12月25日火曜日

[Windows] システム周りな話

[共通] 当 Blog の投稿に関する基本事項について
→ http://fuunyan.blogspot.jp/2012/09/blog.html


開発言語にとらわれないシステム共通な部分の覚書です。

画面サイズの事
GetSystemMetrics で諸々取得可能
SM_CYSMCAPTION タイトルバー 21pixel
SM_CXSIZEFRAME 枠 8pixel


2012年12月12日水曜日

[C#] WinAPI を呼んでみる

[共通] 当 Blog の投稿に関する基本事項について
→ http://fuunyan.blogspot.jp/2012/09/blog.html


以前の投稿内では普通に使っているのですが、特に記載していないようだったので別途投稿してみようと思います。
C# は便利ですが、細かいことをやろうとするとどうしても API に頼ることになります。
では API ってどうやって呼びだすのな部分を今回はネタにしてみました。

using System.Runtime.InteropServices;   // DllImportなど、API呼び出し
namespace CSWinFormTest2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // API を利用するのに必要な宣言(インポートライブラリの宣言)
        [DllImport("user32.dll")]
        // API を利用するのに必要な宣言(インポートライブラリの宣言、オプション指定はこんな感じ)
//        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        // API を利用するのに必要な宣言(関数定義の宣言)
        // static extern は必須。アクセス演算子は任意
        private static extern UInt32 MessageBox(IntPtr hWnd, String lpText, String lpCaption, UInt32 uType);

        // MessageBox() Flags  winuser.h より(一部抜粋)
        private const UInt32 MB_OK                   = 0x00000000;
        private const UInt32 MB_ICONASTERISK         = 0x00000040;
        private const UInt32 MB_ICONINFORMATION      = MB_ICONASTERISK;

        private void button1_Click(object sender, EventArgs e)
        {
            // API の利用方法を確認
            MessageBox(this.Handle, "メッセージ本文", "タイトル部", MB_OK | MB_ICONINFORMATION);

            // 余談:C# では MessageBox.Show があるので、本来上記のような手間は必要はない
            System.Windows.Forms.MessageBox.Show("メッセージ本文", "タイトル部",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}
短いので全部まとめて書いています。
まぁコメント見ていただければわかるかと思います。
DllImport で使用するライブラリを指定して関数定義を宣言。
あとは普通に利用するだけです。

ちなみに複数種類の API を利用したい場合は、その関数毎に定義を各必要があります。
オーバーロードするような場合でも DllImport から書く必要があります。
これがめんどくさいので結局 C++/CLI で作るかぁ~?ってなっちゃいます。
まぁ DllImport から関数定義までが一つの宣言だと思ってあきらめるしかありません。

全体的に見れば C# の方が生産性いいはずなので、できるだけ C# でやっていこうかな、っと。

--- 2012/12/27追記 ----------
よく見に行くサイトをいちいち検索するのがめんどくさいので、こちらに転記させていただいた。
毎度お世話になっております(@IT .NET TIPS Win32 APIやDLL関数を呼び出すには?
APIでの型名
(括弧内は対応するC言語の型)
対応するC#の型
(括弧内は.NET Frameworkでの型名)
HANDLE (void *)System.IntPtr
BYTE (unsigned char)byte (System.Byte)
SHORT (short)short (System.Int16)
WORD (unsigned short)ushort (System.UInt16)
INT (int)
LONG (long)
int (System.Int32)
UINT (unsigned int)
DWORD, ULONG (unsigned long)
uint (System.UInt32)
BOOL (long)bool (System.Boolean)
CHAR (char)char (System.Char)
LPSTR (char *)
LPWSTR (wchar_t *)
System.Text.StringBuilder
LPCSTR (const char *)
LPCWSTR (const wchar_t *)
string (System.String)
FLOAT (float)float (System.Single)
DOUBLE (double)double (System.Double)
Win32 APIでの型名と対応するC#の型 WindowsのDLL(Win32 API)と.NET Frameworkとでは型の管理方法が違うため、実際には型の相互変換(マーシャリング)が行われる。なお、BOOL型の実体はLONG型と同じなので、boolの代わりにintを指定することも可能である。