Agent Skillsnttr-tech/winui4k › add-winui-component

add-winui-component

GitHub

为WinUI 3控件生成Kotlin包装类。通过dump_winmd.py从winmd文件机械提取ABI值,遵循Swing命名规范,在Interop.kt、主包及Gallery中实现内部互操作与API暴露,确保类型安全与一致性。

.claude/skills/add-winui-component/SKILL.md nttr-tech/winui4k

Trigger Scenarios

添加WinUI 3控件的Kotlin包装器 用户请求「コンポーネントを追加」或「コントロールに対応」 扩展现有W*类的WinUI API

Install

npx skills add nttr-tech/winui4k --skill add-winui-component -g -y
More Options

Non-standard path

npx skills add https://github.com/nttr-tech/winui4k/tree/master/.claude/skills/add-winui-component -g -y

Use without installing

npx skills use nttr-tech/winui4k@add-winui-component

指定 Agent (Claude Code)

npx skills add nttr-tech/winui4k --skill add-winui-component -a claude-code -g -y

安装 repo 全部 skill

npx skills add nttr-tech/winui4k --all -g -y

预览 repo 内 skill

npx skills add nttr-tech/winui4k --list

SKILL.md

Frontmatter
{
    "name": "add-winui-component",
    "description": "WinUI 3 コントロールの Kotlin ラッパー (W* クラス) を winui4k に追加する。winmd から ABI 値 (IID \/ vtable スロット \/ enum 値) を機械的に抽出し、internal\/winui の *Interop.kt (XamlInterop など) → com.appkitbox.winui4k パッケージ → Gallery の順に実装する。Use when adding a Kotlin wrapper for a WinUI 3 control (CheckBox, Slider, ToggleSwitch, ComboBox, ProgressBar, ...), when the user asks to 「コンポーネントを追加」「コントロールに対応」「ラッパーを実装」, or when extending an existing W* class with more WinUI APIs.",
    "argument-hint": [
        {
            "WinUIコントロール名": "CheckBox)"
        }
    ]
}

WinUI コンポーネントの Kotlin ラッパー追加

Microsoft.UI.Xaml.Controls 配下のコントロールを、Swing 風の W* クラスとして src/main/kotlin/com/appkitbox/winui4k/ に追加する手順。対象: $ARGUMENTS

鉄則

  • ABI 値 (IID / vtable スロット / enum 値) は必ず tools/dump_winmd.py で winmd から抽出する。 記憶・推測・手書きの値は禁止 (XamlInterop.kt 冒頭の方針)。C# ドキュメントの値もそのまま信用しない。
  • 命名は Swing 風にする: WButton (JButton 風)、WLabel (JLabel 風)、WTextField (JTextField 風)。 KDoc の 1 行目に「J〇〇 風: WinUI 3 の 〇〇。」と対応を書く。
  • KDoc・コメントは日本語。既存ファイルのコメント密度とスタイルに合わせる。

手順

1. winmd を用意する

build/winmd/metadata/Microsoft.UI.Xaml.winmd があれば再利用する。無ければ取得する (バージョンは XamlInterop.kt ヘッダー記載の Microsoft.WindowsAppSDK.WinUI と一致させること):

mkdir -p build/winmd && cd build/winmd
curl -sL -o winui.nupkg "https://api.nuget.org/v3-flatcontainer/microsoft.windowsappsdk.winui/2.2.1/microsoft.windowsappsdk.winui.2.2.1.nupkg"
python -c "import zipfile; zipfile.ZipFile('winui.nupkg').extract('metadata/Microsoft.UI.Xaml.winmd')"

2. ABI 値を抽出する

python tools/dump_winmd.py build/winmd/metadata/Microsoft.UI.Xaml.winmd \
  Microsoft.UI.Xaml.Controls.CheckBox \
  Microsoft.UI.Xaml.Controls.ICheckBox
  1. まずクラス本体をダンプし、default_iface / activatable factory / composable factory / statics を確認する
  2. 次に既定インターフェースと、使う機能が宣言されている基底インターフェース (Primitives.IToggleButton など) をダンプし、guid と vtbl スロットを得る。 各メソッドは vtbl[n]: get_Delay() -> i4 のようにシグネチャ付きで出るので、 引数型 (boolean は 1 バイト、object は box が必要、など) もここで確定する
  3. enum はそのまま型名を渡すと Name = value 形式で出る
  4. delegate (イベントハンドラ型) は Invoke at vtbl[3] と出る。guid も控える。 インターフェースのダンプ末尾に event Toggled: Microsoft.UI.Xaml.RoutedEventHandler の 形式でイベントとハンドラ型 (TypedEventHandler<T1, T2> 含む) が出る
  5. 構造体 (GridLength, Color など) は field Value: r8 の形式でフィールド順が出る
  6. 添付プロパティ (Canvas.Left, Grid.Row, ...) を使うなら IXxxStatics もダンプする (第 1 引数が UIElement か FrameworkElement かはシグネチャで分かる)

継承ツリーの探索が必要なら、クラスの base: をたどって親クラスも順にダンプする。

Windows.UI.Color / Windows.Foundation.Uri / IPropertyValue など OS 側の型は Microsoft.UI.Xaml.winmd に無い。NuGet の microsoft.windows.sdk.contracts (contracts.nupkg) から ref/netstandard2.0/Windows.Foundation.UniversalApiContract.winmd (大半の型) や ref/netstandard2.0/Windows.Foundation.FoundationContract.winmd (IPropertyValue / IReference`1) を 展開して同様に調べる (build/winmd に展開済みならそのまま使う)。

3. *Interop.kt に定数を追加する

ABI 定数は src/main/kotlin/com/appkitbox/winui4k/internal/winui/ に winmd ソース単位で分かれている。 定数の由来 winmd に対応するファイルを選び、既存セクションの形式に合わせる:

ファイル 対象
XamlInterop.kt Microsoft.UI.Xaml.* / Microsoft.UI.Text (大半のコントロールはここ)
WindowingInterop.kt Microsoft.UI.Windowing / Microsoft.UI.Dispatching (Microsoft.UI.winmd)
FoundationInterop.kt Windows.Foundation (コレクション / IReference / ジェネリック delegate のベース IID)
NotificationInterop.kt AppNotifications / BadgeNotifications / JumpList
WebView2Interop.kt WebView2 (Controls.WebView2 + Microsoft.Web.WebView2.Core)
  • // ---- Microsoft.UI.Xaml.Controls.CheckBox ---- のセクションコメント
  • CLS_CheckBox / IID_ICheckBoxFactory / IID_ICheckBox / スロット定数 (ICheckBox_put_XXX = n の形式、末尾コメントにシグネチャの要点)
  • IControl / IContentControl / IButtonBase / IUIElement / IFrameworkElement など 定義済みの共通インターフェースは再定義せず再利用する。追加前に *Interop.kt を検索すること

4. ラッパークラスを作成する

src/main/kotlin/com/appkitbox/winui4k/W<SwingName>.kt を新規作成する。

  • 基底クラス: ButtonBase 派生 (Button / HyperlinkButton / RepeatButton / ...) なら WButtonBase (text / content / command / addActionListener を継承)、 ToggleButton 派生 (CheckBox / RadioButton) なら WToggleButton、 SplitButton 派生なら WSplitButton、その他の Control 派生なら WControl、 Panel 派生 (StackPanel / Grid / Canvas / RelativePanel / ...) なら WContainer (Children の add / removeAll を継承)、 それ以外の FrameworkElement 直系なら WComponent
  • インスタンス生成 (手順 2 のクラス情報で分岐):
    • composable factory あり → Activation.composeDefault(XamlInterop.CLS_X, XamlInterop.IID_IXFactory) (戻り値は既定インターフェースのポインタ)
    • activatable factory: <default IActivationFactory>Activation.activate(XamlInterop.CLS_X).queryInterface(XamlInterop.IID_IX)
  • com.appkitbox.winui4k / internal.winui パッケージで java.lang.foreign を import しない (FFI バックエンド 非依存を保つ規約)。ネイティブメモリ操作が必要なら internal.ffi.apiFfi.backend.withScope { ... } / Ffi.backend.memory / Ptr を使う
  • プロパティ・イベント・enum・構造体・ICommand などの実装パターンは references/patterns.md を必ず読んで踏襲する

5. Gallery にデモページを追加する

winui4k-sample-gallery/src/main/kotlin/com/appkitbox/winui4k/sample/gallery/ はカテゴリごとに 1 ファイル (BasicInputPages.kt / CollectionsPages.kt / ... / WindowingPages.kt) に分かれている:

  • GalleryNavigation.ktpages にページ名 (WinUI のコントロール名) → ::build<Name>Page を、 categories に所属カテゴリへのページ名を追加する
  • 該当カテゴリの *Pages.ktinternal fun build<Name>Page() を実装し、追加した API を 一通り操作できるデモを buildExample("見出し", body) 単位で並べる (// region <Name> ページ で囲み、そのページ専用のヘルパーは private で同じ region に置く。 既存の Button ページの構成に合わせる)
  • ページの骨格 (buildPage / buildExample / optionsLabel) は GalleryScaffold.kt、 テーマ配色 (CARD_BACKGROUND など) は GalleryTheme.kt にある

6. 検証する

./gradlew compileKotlin   # まずコンパイル
./gradlew run             # ウィンドウを開き、追加したデモを目視確認 (ユーザーが閉じると終了する)

実行時に COM 呼び出しが失敗すると HRESULT 例外、Kotlin 側コールバックの例外は [winui4k] exception escaped from COM upcall: として stderr に出る。 スロット番号のずれが典型的な原因なので、失敗したら手順 2 のダンプ結果と突き合わせる。

Version History

  • 6b88d26 Current 2026-07-30 20:19

Same Skill Collection

.claude/skills/kotlin-lint-rules/SKILL.md

Metadata

Files
0
Version
6b88d26
Hash
f2c50e94
Indexed
2026-07-30 20:19

- 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-31 01:53
浙ICP备14020137号-1 $방문자$