PART 2 クラスライプラリピュークラス タの処理について、それらがいつ行なわれるかを考慮しなければならない。 0 ユーサー定義メッセージ ューザーがダイアログの [OK] ボタンをクリックしたときに、モードレスダイアログを削除した い場合を考えてみる。これには問題がある。ューサーが COK] ボタンをクリックしたことを、ビュー がどのようにして知るのか ? ダイアログはビュークラスのメンバ関数を直接呼び出すことができ るが、これはダイアログを特定のビュークラスと「結合」させてしまうことになる。よりよい解決方 法は、 [ OK ] ボタンのメッセージハンドリング関数の呼び出しの結果として、ダイアログがビュー にユーザー定義メッセージを送るということである。ビューがメッセージを受信したとき、ダイア ログウインドウ ( オプジェクトではない ) を削除することができる。これは新しいダイアログ作成の 時点で設定される。 Windows メッセージを送る方法にはふたつの選択肢がある。つまり CWind の & 〃盟ぉ s 〃 ge 関 数か、物財 ge 関数を使うことができる。前者は即座ににメッセージハンドリング関数の呼び出 しを引き起こし、後者はメッセージを Windows のメッセージキューに投入する。 PostMessage を 選択した場合、多少の遅れが存在するので、ダイアログが削除されるのは、ビューがメッセージを 受け取ったときと考えるのが適当である。 0 ダイアログの所有権 こでダイアログがデフォルトのポップアップスタイルを使用すると考えよう。このことは、ダ イアログがビューのクライアント領域に制限されないということを意味する。 Windows が関与し ている限り、ダイアログの「所有者」はビューではなく、アプリケーションのメインフレームウイン ドウである ( 第 12 章で導入される ) 。メッセージをビューに送るためには、ダイアログのビュ 知る必要がある。それゆえダイアログクラスは、コンストラクタが設定するデータメンバを介して、 そのビューを記憶しなければならない。 0 モードレスダイアログの例ーー EX07A 第 6 章のモンスターダイアログをモードレスダイアログに変更することもできるが、より単純な ダイアログに関してスクラッチで始める方が簡単である。例 EX07A はひとつのエディットコント ロール、 [OK] ボタン、 [ キャンセル ] ボタンを持っダイアログを使用するものである。第 6 章の例 と同様に、マウスカーソルがビューウインドウ内部にあるときに、マウスの左ボタンを押すことで ダイアログが現われるが、今回は別のイベント、マウスカーソルがビューウインドウ内部にあると きのマウスの右ボタンの押し下げに応答して、ダイアログを削除するという付加機能を持たせた。 同時にはひとつのダイアログしか許していないので、 2 回目の左ボタンの押し下げが、同じダイア ログを重ねて起動しないようにしなければならない。 以上のステップを要約すると、 EX07A のビュークラスは、ダイアログに対応するオプジェクトを 148
ーとステータスパー 0 ボタンの状態 各ボタンは以下の状態を持っことができる。 13 章 ツーノレノヾ 状態 0 TBBS_INDETERMINATE TBBS_DISABLED TBBS_CHECKED TBBS_PRESSED TBBS_CHECKED ー TBBS_DISABLED 意味 通常の、押されていない状態 ( アップ ) チェックされた状態だが、使用することはできない イネープルされているが、アップでもダウンでもない 使用することはできない チェックされている ( ダウン ) 状態 現在マウスにより選択されている ( 押されている ) ボタンは 2 通りの方法のいずれでも動作することができる。つまり、マウスにより選択されてい るときのみダウンされるブッシュボタンとして、あるいはマウスのクリックによりアップとダウン が切り替わるチェックポックスポタンとしてである。標準のアプリケーションフレームワークのツー ルバーでは、すべてのボタンはブッシュボタンである。 0 ツールバーとコマンドメッセージ ューザーがマウスでツールバーボタンをクリックすると、コマンドメッセージが生成される。 のメッセージは第 12 章で見たメニューコマンドメッセージと同しようにルート付けされる。はと んどの場合、ツールバーボタンはメニュー選択に対応している。たとえば標準のアプリケーション フレームワークのツールバーのディスクボタンは、 [ ファイル ] の [ 上書き保存 ] メニュー選択と等 価である。両方とも ID-FILE-SAVE メッセージを生成するからである。コマンドメッセージを受 信するオプジェクトは、メッセージの生成がツールバー中でのクリックによるものか、あるいはメ ニューからの選択によるものかを知る必要はない。 ツールバーボタンが、メニュー項目を反映している必要はない。しかし等価なメニュー項目を提供 しない場合には、ユーザーがキーポードや Windows のキーポードマクロ出力を使ってコマンドを 起動できるように、ボタンにキーポードアクセラレータを定義しておくことを勧める。アプリケー ションが対応するメニュー項目のないツールバーボタンを持つ場合、 ClassWizard はコマンドと更 新コマンドメッセージのハンドラを定義することができない。その場合読者は自分で関数、メッセー ジマップエントリ、プロトタイプを追加しなければならない。 アプリケーションのメインフレームクラス中で定義されるスタティック配列加は、ボタンに コマンドを関連付けている。 AppWizard が生成した MAINFRM ℃ pp 中に見られる一般的なコー ドを以下に示す。 static UINT BASED_CODE buttons ロ / / ビットマップファイル 'toolbar. bmp' と同じ並び順です。 243
PART 2 クラスライプラリピュークラス 何もしない CE ェ 06 〃 D / bg の 0 〃 OK 関数の記述と、 [OK] ボタンに応答する新しい関数に終了 コードを追加することで、簡単に Enter キーをディスエープルすることができる。以下にステップ を示す。 るものははとんどないので、問題はない。 きないが、 Windows べースのプログラムでは、ボタンに関してダブルクリックを利用す この場合、 0 D ツ召関数はシングルクリックとダブルクリックの区別をすることはで ON_COMMAND (IDC_DELETE , OnDe1ete) 終的に処理される。 らは以下のようにマップされる ON-COMMAND メッセージハンドリングエントリで最 プリケーションフレームワークはこれらのコマンドメッセージの経路を決め、そしてそれ ジ」を生成するという点で、ボタンイベントは特殊である。第 13 章で説明するように、ア ダイアログクラスが上記のような通知ハンドラを持っていない場合、「コマンドメッセー ON_BN_DOUBLECLICKED ( IDC_DELETE , OnDe1eteButtonDb1C1icked) ON—BN_CLICKED (IDC_DELETE , OnDe1eteButtonC1icked) トリを生成する。 を「平坦化」している。 ClassWizard はたとえば以下のような通知メッセージマップエン はかの Windows メッセージと同しレベルに向けさせることで、メッセージ処理ロジック る。 Microsoft 基本クラスライプラリバージョン 2.0 は、コントロール通知メッセージを ツ 'P 川プログラムはこれらの通知メッセージを多重化された switch 文で処理してい 卍の祝襯はボタンハンドルと BN ー CLICKED 通知コードの両方を収めている。ほとんどの ログに送る。たとえばあるボタンがクリックされた場合、 Pa 川襯はボタン ID 、そして ダイアログコントロールは WM_COMMAND 「通知メッセージ」をそれらの親ダイア Windows SDK プログラマ諸氏へ ように、べースクラスの 0 OK 関数を呼び出す。以下にコードを示す。 0 C / な 0 ん関数のボディを書く。この関数はオリジナルの CE ェ 06 〃〃 / 〃 / og の 0 OK と同し バ関数を、コントロール / 〃 C ー OK からの BN ー CLICKED メッセージに対応させる。 CIassWizard を使って 0 C / な 0 んメンバ関数を作成する。この CE 06 〃 D / og クラスのメン ら IDC- OK に変更し、 [ デフォルトフォーカス ] プロバティのチェックをはすす。 し、ダイアログ / D 一のカ 4 ん 0G7 を選択し、次に [ OK ] ボタンを選択する。その ID を / DOK か 1. AppStudio を使って [ OK ] ボタンのを変更する。リソースファイル EX06A. RC をオープン 3. 2. 140
PART 3 ドキュメントービューアーキテクチャ ID_INDICATOR_CAPS , ID_INDICATOR_NUM , ID_INDICATOR_SCRL, アプリケーションの派生フレームクラス中で呼び出される C & 〃 s 召 4 % のメンバ関数 S ル市電 252 pCmdUI—>Enab1e ( : : GetKeyState (VK—CAPITAL) & 1 ) ; void CMainFrame : : OnUpdateKeyCapsLock(CCmdUI* pCmdUI) ON_UPDATE_COMMAND_UI ( ID_INDICATOR_CAPS , OnUpdateKeyCapsLock) ケータをオンにする。 ドラ関数によりハンドルされる。 Caps Lock モードが設定されていた場合、 Enable 関数はインジ れる。 Caps Lock インジケータはフレームクラス中で、以下のメッセージマップエントリとハン タは文字列リソース ID により識別され、同じ ID が更新コマンドメッセージのルート付けに使用さ 関連する更新コマンドメッセージハンドラ関数のロジックにより表示 / 非表示される。インジケー 状態インジケータ区画は、それぞれリソースで提供されるひとつの文字列にリンクされており、 0 状態インジケータ さは表示幅の 1 / 4 、そしてステータスパー中に余裕があれば拡張する。 の区画 ( インデックスが 0 ) の場合、斜面状の境界を持たない伸縮可能な区画となる。その最小の長 通常は、メッセージ行区画の長さは、正確に表示幅の 1 / 4 である。しかし、メッセージ行が最初 pStatus—>SetPaneText(), "message line for first pane") ; (CStatusBar*) AfxGetApp ( ) —>m-pMainWnd—>GetDescendantWindow(ID—MY—STATUS—BAR) ; CStatusBar* pStatus バーへのポインタを取得する。 C ルの Ge の化〃厩ルか関数は、定数 ID-MY-STATUS-BAR で識別されるステータス ので、アプリケーションオプジェクトを介して親フレームウインドウからアクセスする必要がある。 ラスのメンバ関数の一部分である。ビューウインドウはステータスパーウインドウと兄弟に当たる ばならない。区画 0 は左端の区画で、 1 は右隣の区画というように続く。以下のコードはビュ スとするインデックスパラメータを持つ CS s. 召〃の & 卍 4 〃 e メンバ関数を呼び出さなけれ の値を設定するためには、ますステータスパーオプジェクトへのアクセスを取得し、次に 0 をベー メッセージ行区画は、プログラムが動的に供給する文字列を表示する部分である。メッセージ行 0 メッセージ行 んバは、市バ配列の内容に従って、ステータスパーを設定する。
この処理はプロジェクトの RESOURCE. H ファイル中に格納されているシンポルテープルに 3 つの ID を追加する。 3. AppStudi0 を使ってアプリケーションのシンポルを編集する。 [ シンポル ] ツールバーボタン をクリックするか、 [ 編集 ] メニューの [ シンポル ] を選択する。新しいステータスパー識別子 / D ー SI TU. & 召鳳を追加し、デフォルト値を受理する。 4. CIassWizard を使って C 財〃厖襯 e クラスに [ 表示 ] メニューのコマンドハンドラを追加する。 2. 5. 13 章ツールバーとステータスパー プルセグメントを選択し、以下の 3 つの文字列を追加する。 App Studi0 を使ってアプリケーションの文字列テープルリソースを編集する。任意の文字列テー 文字列 ID_INDICATOR_SHIFT ID_INDICATOR_CTRL ID_INDICATOR_ALT 文字列キャプション SHIFT CTRL ALT 以下のコマンドメッセージハンドラを追加する。 オプジェクト ID_VIEW_STATUS_BAR ID_VIEW_STATUS_BAR メッセージ COMMAND UPDATE_COMMAND_UI メンバ関数名 OnViewStatusBar OnUpdateViewStatusBar MAINFRM. H 中に以下の関数のプロトタイプを追加する。 ClassWizard は関係するコマンド メッセージ ID を認識しないので、これらの C 4 切のメッセージハンドラのプロトタイプ を手で設定しなければならない。 afx—msg void OnUpdateKeyShift (CCmdUI* pCmdUI) ; afx—msg void OnUpdateKeyCtrI(CCmdUI* pCmdUI) ; afx—msg void OnUpdateKeyA1t (CCmdUl* pCmdUl) ; FX. ー SG プラケット中にこれらのメッセージハンドラの文を追加すると、以後は CIassWizard でアクセス、編集できるようになる。 6. MA 爪 FRM ℃ PP ファイルを編集する。オリジナルの切市んバ配列を以下のように置き換える。 static ID_SEPARATOR , ID—SEPARATOR, ID_INDICATOR_SHIFT, ID_INDICATOR—CTRL , ID_INDICATOR_ALT UINT BASED_CODE indicators ロ 255 / / メッセージラインの 2 番目の区画 / / メッセージラインの最初の区画
PART 2 クラスライプラリピュークラス BYE をビューに送る。これのハンドリングについては後で扱う。 9. RESOURCE. H を編集して、 / D. ー G00 〃召 ) 五メッセージを定義する。以下のコード行を追加 CEx07aView : : CEx07aView() する。 #define ID_GOODBYE WM_USER + 5 Windows 定数 WM-USER は、ユーザー定義メッセージに使用可能な最初のメッセージ ID で ある。アプリケーションフレームワークはこれらのメッセージのいくつかを使うので、最初の 5 つメッセージをスキップする。 クタはそれを削除する。 る。ビューのコンストラクタはヒープ上にダイアログオプジェクトを生成し、ビューのデストラ クラスは、ビューの CE ェ 0 ん〃 / og オプジェクトを示す襯ーカ〃皙データメンバを持っことにな 10. EX07AVW ℃ PP 中の CE. ェ 0 防夜ん , のコンストラクタとデストラクタを修正する。 CE. ェ 0 防麒 ) に書き戻すので、失われることはない。 出すことはできない。しかし App Studio は終了時に ID-GOODBYE を RESOURCE. H CE. H を読み込むとき、 ID-GOODBYE を無視するので、シンボルのリスト中にこれを見 注意 App Studio はほかの定数を元にした定数を認識しない。 APP Studi0 が RESOUR m-pD1g CEx07aView: nev CEx07aDiaIog(this) ; &CEx07aView() delete m-pD1g; / / ウインドウがまだ破棄されていなければ破棄される 11. ファイル EX07AVW ℃ PP 中の仮想関数 0 D 耀にコードを追加する。ューザーにマウスポタ ンを押すことを促すために、 CE 0 防 e の 0鉈D耀肥関数 (AppWizard により生成された骨 152 EX07AVW ℃ PP のコードを以下のように編集する。 ONDOWN と WM_RBUTTONDOWN メッセージ用のハンドラを追加する。そしてファイル 12. CIassWizard を使って CE. ェ 0 怖麒 ) にマウスメッセージハンドラを追加する。 WM-LBUTT pDC—>TextOut ( 0 , 0 , "Press the left mouse button here. " ) ; void CEx07aView: : OnDraw(CDC* pDC) 格 ) に以下のコードを書く。
2. 3. 4. 4 章基本的なイベントハンドリング—ClassWizard の使用 EX04BVW. H 中の CE ェ 0 イわ怖麒 . , クラスへッダを編集する。 EX04BVW. H ファイル中の CE. ェ 04 わ 怖麒 , 宣言中に以下の行を追加する。 private : CRect m—eIIipseRect ; CPoint m_mousePos ; BOOL m_bCaptured; CIassWizard を使用して 3 つのメッセージハンドラを追加する。前に説明した 3 つのマウスメッ セージ用のメッセージハンドリング関数を追加する。以下に Windows メッセージとそれに対応 するメンバ関数のリストを示す。 メッセージ WM_LBUTTONDOWN WM_LBUTTONUP WM_MOUSEMOVE メンバ関数名 OnLButtonDown OnLButtonUp OnMouseMove EX04BVW ℃ PP 中の CE ェ 0 イわ怖麒 , のマウスメッセージハンドリング関数を編集する。 Class Wizard は先に示した関数の骨格を生成する。 EX04BVW ℃ PP 中からこれらを見つけ、以下に void CEx04bView : : OnLButtonDown(UINT nFIags , CPoint point) 示す太字部分のコードをタイプする ( 既存のコードを置き換える ) 。 : SetCursor( : :LoadCursor(NULL, IDC—CROSS) ) ; / / マウスがキャプチャされている間、 " 十字 " マウスカーソルになる m_mousePos = point ; m—bCaptured = TRUE; SetCapture ( ) ; / / 後続の LButtonUp メッセージのためにマウスをキャプチャしておく 土土 (circle. PtInRegion(point) ) { circle. CreateEIIipticRgnIndirect (m—e11ipseRect) ; point ・ x, point ・ y) ; TRACE ( “ entering CEx04bViev : : OnLButtonDovn ー point CRgn circle ; CRect rect ; void CEx04bView : : OnLButtonUp (UINT nFIags , if (m-bCaptured) { ReIeaseCapture ( ) ; m—bCaptured = FALSE; CPoint point)
PART 2 クラスライプラリピュークラス ビットマップボタンをクリックするとメッセージが現われる。ビットマップボタンは、 App Studio 中で指定した矩形より小さい ( 前記のステップ 4 に示されたダイアログを参照 ) 。アプリケーショ ンフレームワークがビットマップのビットをダイアログ中のピクセルにマップするため、これら は縮小される。 0 さらに進んだビットマップボタン ビットマップボタンは、すでに見てきた「アップ」、「ダウン」状態に加えて、「フォーカスされた」、 そして「ディスエープルされた」状態を想定することができる。ボタンが F で終わるビットマップリ ソース名を持っ場合、そのビットマップはボタンが入力フォーカスを持っている場合に現われるよう になる。リソース名が X で終わる場合は、ビットマップはボタンが ( C ルの E 〃〃わル肥関 数の呼び出しなどを介して ) ディスエープルされている場合に現われる。 C 召″襯ゆお″クラスの より詳しい解説はクラスライプラリリファレンスを参照。 タイマの使用と制御の拠出 マイクロプロセッサの速度に依存しない一定の間隔でプログラムにメッセージを送るように Windows タイマをプログラムすることができる。タイマはアニメーションの速度の制御、アラー ムの起動、擬似マルチタスクの実装、あるいは以下の例で示すような、長い計算処理中の視覚的な 状態表示などに使用することができる。 0 タイマ タイマの使用は簡単である。単にインターバルバラメータとともに C ルの S 行襯げ関数を 呼び出し、そして ClassWizard の助けを借りて WM_TIMER メッセージ用のメッセージハンド ラ関数を用意すればよい。タイマのインターバルを 200 ミリ秒に設定したとすると、 C ルの K 石襯げ関数の呼び出し、あるいはタイマのウインドウが削除されるまで、そのインターバルを ごとに WM_TIMER メッセージが生成される。 タイマをベースにした単純なアニメーションプログラムはありふれたものである。ビューの 0 〃 C 尾 4 関数がタイマを起動し、そしてタイマメッセージハンドラが位置変数を更新し、領域を無効 化する。 0 D 耀関数は位置変数に従って、イメージを描画する。本章の後半の EXIIB サンプル プログラムは、長い計算処理にタイマを使って割り込みをかけるという点で、多少は興味深いもの だ。タイマで実験している間に、読者は Windows メッセージ処理に関してさらに学び、独自のマ ルチタスクアプリケーションを作成するための多少の洞察を得るだろう。 206
4. 6 章モーダルダイアログ [ スペシャル ] ボタンにメッセージハンドリング関数を追加する。ダイアログ管理のほとんどは、 Windows の助けにより CD / og べースクラスが行なうので、 CE. ェ 06 〃 D / og は多くのメッセー ジハンドリング関数を必要としない。たとえば、 COK] ボタンの ID を IDOK に指定した場合 (CIassWizard のデフォルト ) 、ユーザーがボタンをクリックしたとき、 CDiaIog の仮想関数 0 れ OK が呼び出される。しかしほかのボタンについては、メッセージハンドラが必要である。 <CIassWizard>Y イアログは、 [ オプジェクト ID] リストボックス中に / DC. ー SPEC. / んの工 ントリを収めている。このエントリをクリックし、 [ メッセージ ] リストボックス中に現われる BN_CLICKED メッセージをダブルクリックする。 ClassWizard はメンバ関数名 0 〃 C d 召 を反転し、以下のように < メンバ関数の追加 > ダイアログをオープンする。 ゞ関数名 : 。 On 0 雇 kedS 「 ci 引 OK ラセル 勺しア ( 罅 ここに独自の関数名をタイプすることができるが、今回はデフォルトを受け入れるので [OK] を クリックする。次に < ClassWizard> ダイアログ中の [ コードの編集 ] ボタンをクリックする。 これにより VisuaI Workbench 中でファイル EX06ADLG ℃ PP がオープンされ、カーソルが 0 C ん / 関数に移動する。 0 C / なん e じ / 関数中で、既存のコードを置き換えて、 以下の太字部分のコードをタイプし、 T. 鳳 CE 文を挿入する。 void CEx06aDiaIog: :OnCIickedSpecia1() TRACE("CEx06aDia10g : : OnC1ickedSpecia1\n") ; 5. CIassWizard を使用して、 072 ル / の / og メッセージハンドリング関数を追加する。この後で見 ることになるが、 ClassWizard はダイアログコントロールを初期化するコードを生成する。し かしこの DDX (DiaIog Data Exchange) コードはリストボックスの選択肢の初期化を行なわな いので、 CDialog の 0 の / og 関数をオーバーライドしなければならない。 0 ル / の / og は仮想メンバ関数であるが、 WM_INITDIALOG メッセージを派生ダイアログクラス中でマッ プした場合には、 ClassWizard はプロトタイプを生成することができる。これを行なうには、 ます VisuaI Workbench の [ プラウズ ] メニューから [ClassWizard] を選択する。 [ オプジェク ト ID] リストボックス中の CF ェ 06 〃の / og をクリックし、次に [ メッセージ ] リストボックス中 で WM_INITDIALOG をダブルクリックする。そして <ClassWizard>Y イアログ中の [ コー ドの編集 ] ボタンをクリックして、 0 ル / の / og 関数を編集する。既存のコードを置き換えて、 以下の太字部分のコードをタイプする。 135
PART 3 ドキュメントーピューアーキテクチャ 用意されるメニュー項目とコマンドメッセージハンドラは、 AppWizard 中で選択したオプショ ンに依存する。たとえば印刷を選択しなかった場合は、 [ 印刷 ] と [ 印刷プレビュー ] のメニュー項目 は得られない。印刷はオプションなので、 C 怖召肥クラス中ではメッセージマップエントリは定義さ れないが、派生ビュークラス中では生成される。なぜなら、次のようなエントリは C 怖麒 ) クラス ではなく、 C/ な怖砒 , クラス中で定義されるからである。 ON_COMMAND(ID_FILE_PRINT, CView: : OnFi1ePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView: : OnFiIePrintPreview) メニュー項目のイネープル / ティスエープル アプリケーションフレームワークは、現在のコマンドルートにコマンドメッセージハンドラが見つか らなかった場合に、メニュー項目をディスエープルすることができる。この機能は、 ON-UPDATE- CO 財財ル〃ーこ〃メッセージハンドラを利用するときの問題の助けになる。 CF 襯 e ルのデータ メンノヾ襯ーわ 0 盟 e ″ E 〃勧んを FA ん SE に設定すると ( デフォルト ) 、この機能をディスエープル することができる。 ひとつのドキュメント用にふたつのビューがあり、最初のビューだけが / DM. ー / 00 財コマンド用 のメッセージハンドラを持っている場合を考えてみる。フレームメニューの [ ズーム ] 項目は最初の ビューがアクテイプなときにのみイネープルされる。別の例として、アプリケーションフレームワー [ 貼り付け ] メニュー項目を提供しているとしよう。派生さ クが [ 編集 ] に [ 切り取り ] 、 [ コピー ] 、 あるいはドキュメントクラス内にメッセージハンドラが提供されていない場合、これ れたビュー らはディスエープルされる。 CEdit Vie Ⅳクラス 本章はコマンドメッセージに焦点を当てているが、 CEdit 防麒 ) クラスはそこで傑出した役回りを 演じている。このクラス自身は C 巧麒 , から派生しているが、アプリケーションのカスタムビュー クラスのべースクラスとして提供される。 CEditView から派生させたクラスのオプジェクトは、コ マンドメッセージを処理することができるという点で、 C 怖肥オプジェクトに似ている。これは また、テキスト編集とフォーマッティングが可能という点で、 CEdit オプジェクトにも似ている。 CE イ″怖 e オプジェクトは、実際にはそのクライアント領域全体がエディットコントロール子ウィ ンドウに占められている、通常のビューオプジェクトである。クラスのメンバ関数は、このふたっ の関連したウインドウを、ひとつのオプジェクトとして動作させる。テキスト入力が必要なときに 理想的なツールである。 工ディットコントロールについてだが、 CEditView オプジェクトのテキストは、オプジェクトの CE ″部の奧深くに収められている。このテキストにアクセス ( その他、ウインドウと対話 ) するた 226