MATLAB ちゃん開発記録 #3 MATLAB ちゃんをオーバーレイ表示する（MATLAB + .NET）

# この記事は？
- [MATLAB ちゃん開発記録 #1（MATLAB + VOICEVOX + ChatGPT）](https://qiita.com/macht/items/661b6085cc6332373075)
- [MATLAB ちゃん開発記録 #2 MATLAB ちゃんと音声で会話する（MATLAB + Whisper）](https://qiita.com/macht/items/1b0db53ee155105e3b76)
- [MATLAB ちゃん開発記録 #3 MATLAB ちゃんをオーバーレイ表示する（MATLAB + .NET）](https://qiita.com/macht/items/bb9516baa6351024c501)←本記事

MATLAB ちゃん開発記録も 3 回目の投稿になりました。ここまでの記事で、MATLAB と ChatGPT, VOICEVOX, Whisper を繋げて音声会話を行うことができるようになったので、機能面でいえば MATLAB ちゃんアプリはほぼ完成と言ってもよいかと思います。

ただし、見た目に関してはまだまだ改善の余地がありそうです。現状、MATLAB ちゃんを起動するとアプリウィンドウが立ち上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482141/a2a3e5ff-3ac0-d2bd-cf37-37c1e04b6c3e.png)
MATLAB ちゃんと会話することだけが目的であればこれでも全然いいんですが、

- 作業中の息抜きに会話する
- コードを書いててわからないところを聞いてみる

といった用途を考えた場合、ウィンドウ形式で表示されると別の作業の邪魔になってしまうので、あまりよろしくありません。

画面上にキャラクターと吹き出しだけ表示され、それ以外の背景部分が透過しているような見た目（いわゆるオーバーレイ表示）にできれば、より気軽に会話を楽しむことができるようになりそうですよね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482141/fe328c5d-e786-5437-3aa2-f6d92526dd31.png)
↑イメージとしてはこんな感じ。吹き出しの色が黄色いのに特に理由はありません ~~（お前を消す方法）~~。

ということで、今回はこれを目標に MATLAB ちゃんを改造していきたいと思います！

# 1. オーバーレイ表示するには
色々と調べてみたのですが、残念ながら、App Designer を使って作られるアプリは、オーバーレイ表示に対応していないみたいです。背景の透過などができないため、どうしてもウィンドウが表示されてしまいます。悲しみ。

まあでも、MATLAB の機能だけでできないとわかってからが MATLAB 芸人の腕の見せ所。ということで、まずは MATLAB 関係なく、そもそもオーバーレイ表示のアプリってどうやって作るのかを調査します。


ネットの海を ~~カイル君のように~~ 泳ぎ回っていたら、以下の記事を見つけました。

[Windowsでオーバーレイフォームを作った](https://qiita.com/kumaS-kumachan/items/ebbc7e9abefc610fb327)

こちらの記事は、.NET の System.Windows.Forms を使ってオーバーレイフォームを作成する、というもの。.NET のフォームは、背景色やツールバー表示を細かく設定できるみたいです。

<br>
<br>

**<font Color="Red">……これは使える！</font>**

<br>
<br>

実は、MATLAB は特別な設定なしに .NET を呼び出すことができます。

[MATLAB からの .NET の使用](https://jp.mathworks.com/help/matlab/matlab_external/using-net-from-matlab-an-overview.html)

MATLAB で System.Windows.Forms の各機能を呼び出せば、オーバーレイフォームが作れるはずです。


# 2. MATLAB でオーバーレイフォームを作ってみる
ということで、早速 MATLAB でオーバーレイフォームを作ってみます。

## 2.1 フォームの作成
まずは環境のセットアップをします。

```MATLAB
NET.addAssembly("System.Windows.Forms");
import System.Windows.Forms.*
```

この 2 つのコマンドを実行することで、MATLAB 上で System.Windows.Forms の機能が使えるようになります。早速フォームが作れるか確認。

```MATLAB
f = Form;
f.Show
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482141/8de0209c-88db-27e9-e82e-dfcde8a92990.png)
小さなフォームが表示されました（なんかかわいい）。これだと少し小さすぎるので、サイズを弄ってみます。Forms の [Size プロパティ](https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.form.size?view=windowsdesktop-7.0)を弄ればいけるかな……？

```MATLAB
>> f.Size = [400,400]
クラス 'Form' のプロパティ 'Size' の設定中にエラーが発生しました:
値は 'System.Drawing.Size' でなければなりません。
```

あれ、なんかエラーが出た。どうも Size プロパティには直接値を代入しちゃダメみたいですね。もう一度 [Size プロパティ](https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.form.size?view=windowsdesktop-7.0)のドキュメントを見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482141/fcab8b6e-be1a-1971-63f9-04eaf6c32aab.png)
思いっきり System.Drawing.Size 型って書いてありました、ごめんなさい……。
ということで、データ型を変更して再挑戦。

```MATLAB
import System.Drawing.*
f.Size = Size(400,400);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482141/95f8ec84-8469-d39b-a36e-6119013db173.png)

今度はエラーなく実行できました！ちゃんと大きくなっていますね。

## 2.2 画像の追加
次に、作成したフォーム上に MATLAB ちゃんを表示してみます。フォームに画像を追加する場合は、

1. PictureBox を作成し、サイズなどを設定
1. PicturBox の Image プロパティに画像を指定
1. Controls.Add メソッドで PictureBox をフォームに追加

という流れでコードを書けばいいみたいです。[こちらの記事](https://dobon.net/vb/dotnet/graphics/pictureboximage.html)なども参考にしながら、MATLAB ちゃんを表示してみます。

```MATLAB
pbox = PictureBox;
im = Image.FromFile("MATLABちゃん.png");
pbox.Image = im;
pbox.Size = Size(300,300);
pbox.SizeMode = PictureBoxSizeMode.StretchImage; % Box サイズに合わせて画像を表示
pbox.BackColor = Color.Transparent; % 背景を透過
f.Controls.Add(pbox);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482141/03241cb8-94c5-c2fa-09d6-45c60b74e6cd.png)


MATLAB ちゃんが表示されました！

# 2.3 オーバーレイ表示
それでは肝心のオーバーレイフォーム化に挑戦。さっきの記事によると、"FormBorderStyle" と "TransparencyKey" を弄ればいけるはず……。

```MATLAB
f.TransparencyKey = f.BackColor;
f.FormBorderStyle = FormBorderStyle.None;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482141/01978f33-d7a7-e1c2-0a34-a67b8f574f0b.png)

うおー、できたー！！！MATLAB 上に MATLAB ちゃんがオーバーレイ表示されました！
この調子で、テキストフィールドや送信ボタン、吹き出しの画像などを追加してあげましょう！

<details><summary>最終的なスクリプト</summary>

```MATLAB
NET.addAssembly('System.Windows.Forms');
import System.Windows.Forms.*
import System.Drawing.*
f = Form;
f.Show;
f.StartPosition = FormStartPosition.Manual;
f.Location = Point(1000,0);
f.Size = Size(1000,300);
f.BackColor = Color.FromArgb(250,250,250);

f.TransparencyKey = f.BackColor;
f.FormBorderStyle = FormBorderStyle.None;
f.TopMost = true;

pbox = PictureBox;
im = Image.FromFile("MATLABちゃん.png");
pbox.Image = im;
pbox.Size = Size(300,300);
pbox.SizeMode = PictureBoxSizeMode.StretchImage;
pbox.BackColor = Color.Transparent;

pbox2 = PictureBox;
im = Image.FromFile("fukidashi.png");
pbox2.Image = im;
pbox2.Size = Size(600,200);
pbox2.Location = Point(250,10);
pbox2.SizeMode = PictureBoxSizeMode.StretchImage;
pbox2.Parent = pbox;

tbox = TextBox;
tbox.Size = Size(450,100);
tbox.Location = Point(100,20);
tbox.Text = "こんにちは！MATLABちゃんです！何かお困りのことはありますか？";
tbox.Multiline = true;
tbox.ScrollBars = ScrollBars.Both;
tbox.ReadOnly = true;
tbox.Parent = pbox2;

tbox2 = TextBox;
tbox2.Size = Size(400,100);
tbox2.Location = Point(100,150);
tbox2.Text = "質問内容を入れてね！";
tbox2.ImeMode = ImeMode.On;
tbox2.Parent = pbox2;

button = System.Windows.Forms.Button;
button.BackColor = SystemColors.Control;
button.Size = Size(75,25);
button.Location = Point(500,150);
button.Text = "送信";
button.Parent = pbox2;

f.Controls.Add(pbox2);
f.Controls.Add(pbox);
```

</details>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482141/9ce9b3d0-0bc8-9381-3868-e02682f05c6c.png)

オーバーレイフォーム版の MATLAB ちゃんが出来上がりました！


# 3. コールバックの作成
とりあえず見た目については完成しましたが、当然、MATLAB ちゃんが動くためにはボタンを押したときのコールバックを作ってあげる必要があります。

コールバックはフォームのコンポーネントと紐づける必要があるので、「さすがに C# で書かないとダメかな～」と思っていたのですが……

[MATLAB による .NET イベントの使用](https://jp.mathworks.com/help/matlab/matlab_external/use-net-events-in-matlab.html)

>以下の例では、関数 addlistener を使用して、MATLAB® コールバックで .NET イベントを処理します。

なんと、MATLAB の addlistener 関数でフォーム側のイベントを直接キャッチできちゃうみたいです。便利……。

早速、さっき作ったボタンに簡単なコールバックを設定してみます。

```MATLAB
addlistener(button,"Click",@(~,~,~) disp("Pushed!")); % ボタンが押されたらコマンドウィンドウに "Pushed!" と表示
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482141/2e7b9b4c-451b-c6b7-86c9-748abb75c60c.png)
ちゃんと反応しました！

あとは、App Designer で既に作っていたボタンコールバックを（少し改造して）移植してあげれば……
<br>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">仕事終わりにMATLABちゃん開発。<br><br>オーバーレイ表示により、MATLABちゃんにすぐに相談できるようになりました（VOICEVOX の音声でしゃべります）！<br>例のイルカよりは使いやすいはず……<br><br>近々 Qiita で関連記事書くかもです。 <a href="https://t.co/5dKTcHoG6S">pic.twitter.com/5dKTcHoG6S</a></p>&mdash; マハト@MACHTLAB (@mahato_stragule) <a href="https://twitter.com/mahato_stragule/status/1686302324975861760?ref_src=twsrc%5Etfw">August 1, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<br>
みんなの MATLAB ライフを支えるスーパーAI、MATLAB ちゃんの完成です！

# 5. まとめ
ということで、ついに MATLAB ちゃんのオーバーレイ表示に成功しました！実は、一番最初はこういうヘルパーアプリをイメージして MATLAB ちゃんの開発に着手し始めたところもあるので、思った通りの見た目になってめちゃくちゃ嬉しいです。

それにしても、オーバーレイ表示すると一気に公式の機能っぽくなりますね。MATLAB ちゃんを startup.m に仕込んておいて、MATLAB を起動したときに MATLAB ちゃんも一緒に立ち上がるようにしておくと面白そう……


<br>
<br>
<br>
<br>
<br>
<font color="Red"><strong>※"いいね" が増えるほど、MATLAB ちゃんが多機能になります（予定）</strong></font>