カタバミさんのプログラミングノート

日曜プログラマーがプログラミング関係のメモを記録するブログです。

C#でWin32 API TaskDialog関数を呼び出すサンプルコード

C#でTaskDialogを表示するにはWin32 APIのTaskDialog関数(comctl32.dll)を呼び出すサンプルコードです。適当なC#Windows フォーム アプリケーション (.NET Framework) プロジェクトのForm1にボタン(Button1)を作成して、Clickイベントの名前を合わせて実行してください。

関数の呼び出し自体よりもMAKEINTRESOURCEマクロを使用したTD_WARNING_ICONの定義の方が難関だと思います。C/C++におけるintの(WORD)キャストによるビット操作はuncheckedとビット演算子またはキャストにより実施可能です。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace TaskDialogSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private static class NativeMethods
        {
            [DllImport("comctl32.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
            public static extern int TaskDialog(
                IntPtr hwndOwner,
                IntPtr hInstance,
                string pszWindowTitle,
                string pszMainInstruction,
                string pszContent,
                TaskDialogCommonButtonFlags dwCommonButtons,
                IntPtr pszIcon,
                out int pnButton);
        }

        // MAKEINTRESOURCEに対応した変換
        // 単純にnew IntPtr(-1)等とするとWORDへのキャストが実施されずエラーとなる。
        private static IntPtr TD_WARNING_ICON => new IntPtr(unchecked((ushort)-1));
        private static IntPtr TD_ERROR_ICON => new IntPtr(unchecked((ushort)-2));
        private static IntPtr TD_INFORMATION_ICON => new IntPtr(unchecked((ushort)-3));
        private static IntPtr TD_SHIELD_ICON => new IntPtr(unchecked((ushort)-4));

        /// <summary>
        /// TASKDIALOG_COMMON_BUTTON_FLAGS
        /// </summary>
        [Flags]
        public enum TaskDialogCommonButtonFlags
        {
            OKButton = 0x0001,
            YesButton = 0x0002,
            NoButton = 0x0004,
            CancelButton = 0x0008,
            RetryButton = 0x0010,
            CloseButton = 0x0020
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            NativeMethods.TaskDialog(
                Handle,
                IntPtr.Zero,
                "TaskDialogSample",
                "Main Instruction",
                "Content",
                TaskDialogCommonButtonFlags.OKButton,
                TD_SHIELD_ICON,
                out var button);
        }
    }
}