かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

C#からWin32API叩く

P/Invokeもいいですが、C++/CLI経由も個人的に好きです。例えばアクティブなWindowのタイトルを取りたいときとか…。

C++/CLIでこんなクラスを用意しておく。

// CPPCLR.h

#pragma once
#include "Stdafx.h"
#include <Windows.h>
#include <tchar.h>

using namespace System;

namespace CPPCLR {

    public ref class ActiveWindow
    {
    public:
        static String^ GetActiveWindowText()
        {
            GUITHREADINFO info;
            info.cbSize = sizeof(GUITHREADINFO);
            ::GetGUIThreadInfo(NULL, &info);
            WCHAR str[1024];
            ::GetWindowText(info.hwndActive, str, 1024);
            return gcnew String(str);
        }
    };
}

このままだとリンカエラーになるので、プロパティのリンカーの入力にある、追加の依存ファイルを編集して、user32.libとかを追加するようにする。編集画面開いてOK押すだけでよさそう。

C#側は、C++/CLIのプロジェクトを参照して普通に呼び出すだけですね。

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    timer = new DispatcherTimer();
    timer.Tick += (s, args) =>
    {
        info.Text = CPPCLR.ActiveWindow.GetActiveWindowText();
    };
    timer.Start();
}

込み入った値を返すとか、コールバックが必要とかそういうのじゃなければ割とサクッと作れて便利です。