かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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();
}

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