たびとの旅路 ~電脳砂漠の冒険譚~

フロッピー頼りに歩き、クラウドの地平を見つめる今日まで。見つけたオアシス、迷い込んだ砂の迷宮、全てこの羊皮紙に。

古の魔法を現代に蘇らせよ ~.NETとWin32APIで、世界の境界線を操る~

どうやら一筋縄ではいかない砂の迷宮に迷い込んだらしい。 この顛末を書き残しておくか。

遥か昔、Windows XPという時代。 私は.NET Framework(旧開発フレームワーク)という魔法を手にWin32 API(Windows基本機能群)という古の呪文を数多く詠唱していた。 しかし、時代は流れ、魔法体系は.NET 6(最新フレームワーク)へと進化した。 果たして現代の言葉で、あの古の魔法は再び詠唱できるのだろうか?

その答えを探すため、私は一つの実験を試みることにした。 「タスクバーを自動的に隠す」…Windowsという世界の境界線(タスクバー)を操るささやかな魔法。 これを.NET 6という新たな大地で再現する。 これは失われし古の魔法を現代の技術で蘇らせる一人の魔法使いの冒険の記録である。

この羊皮紙のあらまし

この羊皮紙が導く者

  • Win32 APIという古の魔法を現代の言葉で詠唱することに興味がある探求者
  • .NET 6という新たな大地で、失われた魔法を蘇らせる術を知りたい冒険者
  • Windowsという世界の、根源的な理を書き換えることに喜びを感じる者
  • 過去の.NET Framework資産を.NET 6で活用する方法を探している技術者

砂漠の道標

  • Win32 API - Windowsの基本機能群。C言語時代から存在する古典的なプログラミングインターフェース。
  • .NET Framework - マイクロソフトの旧開発フレームワーク。Windows専用の技術基盤。
  • .NET 6 - 最新の.NET統合プラットフォーム。クロスプラットフォーム対応で現代的。
  • タスクバー - 画面下部(または側面)のバー。起動中のアプリケーションやシステム情報を表示する。
  • DllImport - C#から外部のDLL関数を呼び出すための宣言。Win32 API連携の要。
  • マーシャリング - 異なるプログラミング環境間でデータ型を変換する処理。相互運用の基本。
  • StructLayout - 構造体のメモリ配置を制御する属性。Win32 API連携で必須。
  • コンソールアプリ - 文字ベースの対話型アプリケーション。GUIを持たないシンプルなプログラム。
  • WSL2 - Windows Subsystem for Linux 2。Windows上でLinuxを動かす仮想環境。

第一の儀式:古の魔法との契約(Win32 APIの定義)

我々が呼び覚ますのはFindWindow(ウィンドウ検索)とSHAppBarMessage(アプリケーションバー制御)という二つの古の魔法だ。 これをC#(プログラミング言語)という現代の言葉で詠唱できるようDllImport(外部関数宣言)という契約の呪文でその存在を定義する。

// 世界の境界線(タスクバー)を見つけ出す魔法
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
extern static IntPtr FindWindow(...);

// 境界線に命令を下す魔法
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
extern static UIntPtr SHAppBarMessage(...);

同時に魔法に必要なAppBarData(アプリケーションバー情報)という神器の構造もStructLayout(構造体配置指定)の呪文で正確に再現せねばならない。

最終儀式:魔法の詠唱と、世界の書き換え(ソースコード)

全ての準備は整った。 いよいよ世界の境界線の理を書き換える究極の呪文を詠唱する。 祭壇はVisual Studio 2022(統合開発環境)で創り出した.NET 6のコンソールアプリ(文字ベースアプリ)という、ごく簡素なものだ。

using System.Drawing;
using System.Runtime.InteropServices;

// ...(DllImportと構造体の定義は前述の通り)...

// Windowsという大地でなければ儀式は執り行えない
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    Console.Error.WriteLine("Windows で実行してください。");
    return;
}

// 現在の境界線の状態を読み解き、逆の状態へと書き換える
if (ABS_AUTOHIDE == GetTaskbarStatus())
{
    Console.WriteLine("Auto hide -> Always on top"); // 隠れているなら常に表示せよ
    SetTaskbarStatus(ABS_ALWAYSONTOP);
}
else
{
    Console.WriteLine("Always on top -> Auto hide."); // 表示されているなら自動で隠れよ
    SetTaskbarStatus(ABS_AUTOHIDE);
}

// 境界線の現在の状態を読み解く呪文
uint GetTaskbarStatus()
{
    var data = new AppBarData { hWnd = FindWindow("System_TrayWnd", null) };
    data.cbSize = (UInt32)Marshal.SizeOf(data);
    return (uint)SHAppBarMessage(ABM_GETSTATE, ref data);
}

// 境界線の状態を書き換える呪文
uint SetTaskbarStatus(uint option)
{
    var data = new AppBarData
    {
        hWnd = FindWindow("System_TrayWnd", null),
        lParam = (Int32)option
    };
    data.cbSize = (UInt32)Marshal.SizeOf(data);
    return (uint)SHAppBarMessage(ABM_SETSTATE, ref data);
}

この呪文を唱えるたび、世界の境界線はその姿を変える。

タスクバーが常に表示されている状態

常に表示されている世界の境界線

タスクバーを自動的に隠す状態

そして主の呼びかけを待つ控えめな境界線へ

異世界での実験:WSL2 Ubuntu

興味深いことに、このWindows専用の古の魔法をWSL2 Ubuntu(Windows上のLinux環境)という異世界で詠唱しようとしてもビルド(コンパイル)は成功してしまう。 しかし、実行すれば「ここはWindowsではない」と我々の世界の理が正しく作動し、儀式は失敗に終わる。

$ dotnet run
Windows で実行してください。

羊皮紙を巻く前に

.NET 6という現代の魔法体系の中で、Win32 APIという古の魔法を詠唱する旅は、想像以上にスムーズなものだった。 .NET Framework時代とほぼ同じ感覚で、失われたはずの力を呼び覚ますことができる。 これは過去の膨大な資産を持つ我々冒険者にとって、大きな希望だ。

Win32 API連携の重要なポイント

  1. DllImportによる契約 - 古の魔法を現代の言葉で定義する基本手法
  2. StructLayoutの正確性 - 構造体のメモリ配置を正確に再現することが成功の鍵
  3. プラットフォーム判定 - RuntimeInformationで実行環境を確認し、適切なエラーハンドリングを実装
  4. レガシー資産の活用 - .NET Framework時代の知識がそのまま.NET 6で通用する

注意すべき点

かつての古文書に記された呪文は、マーシャリングという異世界との橋渡しの作法が不完全なものが多い。 現代で蘇らせる際は、その作法を注意深く見直す必要がある。

まとめ

この羊皮紙が、同じようにWindowsという世界の深淵を覗き込み、その理を書き換えようと挑む未来の冒険者の助けとなることを願う。 古の魔法は決して失われてはいない。 ただ、新たな言葉で詠唱する術を知る者が少ないだけなのだ。

おっと、どうやら相棒が腹を空かせたようだ。 今日はこのへんで筆を置くとしよう。

砂漠で見つけた魔法のランプ

ラクダの独り言

ご主人が「世界の境界線を消したり出したりする!」とか言って、また黒い画面に呪文を打ち込んでいる。 俺に言わせりゃ、そんなもん、必要な時に見えりゃそれでいいだろうに。 まったく、人間ってのは、どうでもいいことにこだわるもんだな。 しかも「古の魔法を蘇らせる」だとさ。 ご主人にとっちゃ冒険かもしれねえが、俺から見りゃただの画面いじりだ。 おっと、喉が渇いてきやがった。