現在【PropertyGrid】シリーズが進行中ですが、どういう訳かWebを見ていて「あー、昔BCCSkeltonでANSI用、その後ECCSkeltonでUnicode用エディターを作ったRichEditコントロール、懐かしいなぁ。一つ、サンプルのテキストエディターを改造してC#で簡単なRichEditorを作ってみようかしら?」などと、私は発作的に考えてしまいました。
しっかし、これが全然簡単ではない!
ツールバーのボタンをやり直したり、透明化にてこずったりしてなかなか前に進みません。(【PropertyGrid】をほっぽらかして)旧いメニュー関連コードをMenuStripを使ったコードに書き直したりしていると、またまた思ったような動作をしません。
さんざんっぱら、試行錯誤を繰り返し、何とか少し前進したのですが、色々とトラップに嵌ったことが判り、それを【無駄話】のネタにしようと考えましたが、余りにつかれて面倒臭いので、Chat-GPTに書かせてしまいました。(あー、ドンドン馬鹿になってゆくなぁ。)
1. メニューは「ウィンドウ属性」ではなく「コントロール」
-
Win32 API: メニューはウィンドウに結びつく特別枠。
GetClientRectで取得したクライアント領域は自動でメニュー高さを除外 -
WinForms:
MenuStripは単なるControl-
ClientSizeに高さは反映されない -
描画上は上に見えるが、プログラム的には自分で領域を計算する必要がある
-
2. Docked コントロールは追加順(FILO)で積み重なる
-
MenuStrip,ToolStrip,StatusStripはすべてDock = Top/Bottomのコントロール -
Controls.Add() の順序 = Z-order
-
後に追加したものほど上に表示される
-
例: 「先にツールバー追加 → 後にメニュー追加」ならメニューが上に来る
-
順序調整には
Controls.SetChildIndex(menuStrip, 0)も利用可能
-
3. アクセスキーとショートカットキーの区別
-
Win32:
&Nをつけると Alt+キーで動く -
WinForms:
-
Text = "新規(&N)"→ Alt+N でアクセス -
ShortcutKeys = Keys.Control | Keys.N→ Ctrl+N でショートカット -
アクセスキーとショートカットキーは別に設定する必要がある
-
4. クライアント領域計算は自分で行う
-
MenuStripやToolStripの高さを考慮して描画領域を求める必要あり -
例:
int usableHeight = this.ClientSize.Height - menuStrip.Height - toolStrip.Height - statusStrip.Height;
5. イベント処理も Win32 とは異なる
-
Win32:
WM_COMMANDメッセージで処理 -
WinForms:
ClickイベントやCheckedChangedなどでハンドラを登録 -
メニュー/ツールバー/コントロールごとに個別にイベントを設定する
6. Designer とコードの順序に注意
-
デザイナを使う場合、コントロールの追加順や Dock 順序が自動で決まる
-
手動でコードを書く場合は、追加順が Z-order に直結するので注意
💡 まとめ
WinForms は「すべてコントロール」として統一された設計
-
メニューもツールバーもステータスバーも同じ扱い
-
そのため、Win32 API 時代の「自動で領域を除外」「ウィンドウ属性」の感覚は通用しない
移行時は クライアント領域計算・Z-order・ショートカットキー設定・イベント登録 に注意するとスムーズにコーディングできる。(以下は参考図)
どうでしょうか?少しは参考になったかしら?
ps. 現在のRichTextBoxを使ったエディターの状況はこの(↓)通り。
ほぼ80%の機能はカバーできましたが、後印刷と「検索、置換(注)」で躓いています。
注:Win32のコモンダイアログである「検索、置換ダイアログ(FindText関数、ReplaceText関数で呼び出す)」であれば、BCCSkeltonのCREDITクラスで簡単に、
bool CMyWnd::OnFind(HWND hWnd) {
Edit.SetHandle(GetDlgItem(hWnd, IDC_CHILD_CONTROL));
m_hDlg = Edit.m_hFRDlg = FindText(Edit.SetFRDlg('F'));
return TRUE;
}
bool CMyWnd::OnReplace(HWND hWnd) {
Edit.SetHandle(GetDlgItem(hWnd, IDC_CHILD_CONTROL));
m_hDlg = Edit.m_hFRDlg = ReplaceText(Edit.SetFRDlg('R'));
return TRUE;
}
行えたのですが、C#では「検索、置換ダイアログ」が無い、ということらしく、一から始めなければなりません。┐(´д`)┌ヤレヤレ
ps. of ps 大分RichTextBoxのエディターに嵌ってしまいましたが、大丈夫、【PropertyGrid】は覚えていますので、ちゃんと終了させます。

