[[BORLAND C++]]
INDEX
Section.20 Misc
色々やってみよう!ってのが、今回のテーマなのだ。結果だけ見えれば良いという、事務的なプログラムでは、あまり出番の無いものであるが、コンボボックス,ツールバー,ステータスバーや、複数のリソースファイルの話など、十把一絡げにやってしまおうって所だ。てゆーか、自分が忘れない為のメモだな。ついでにちょっとお詫び,今回のサンプル番号だが、前回と入れ子になっているのだが、22番のサンプルを造ってる時に、ウインドウプロシージャのクラス化をする話になって、そちらを先にやってたら、番号が入れ替わってしまった。収集付かなかったのでそのまま出したぞ。

サンプル22のソースコード

  • リソースファイルを複数コンパイル,リンクさせる事は可能か?
    可能だ!こんな事は、やってみれば分かるのだが、ダイヤログの定義が多くなってきてしまったら、別にリソースファイルが、絶対に1本である必要は無いので、幾つかに分割して書いて、リソースコンパイラを複数回実行してリンクさせれば良い。但し、リソースファイルが幾つかに分割されるという事は、ファイル名も異なるものが幾つか出来る訳だから、コンパイルする時に、リンク先を指定するのは必須となるのだ。因みに、今回のサンプルでは、以下の通り、ファイル名の違うリソースファイルは、リンク先を指定してリンクさせる様にした。
    BCC32 -W test022.cpp
    BRC32 test022.rc
    BRC32 -fetest022 tst022.rc


  • コンボボックスの話
    これもついでなのだが、CWCCの方で、コンボボックスを使ったので、ちょっと書いておこうというところだな。今回は、ダイヤログボックスで、簡単にしてしまったが、メインWindowに置く場合は、CreateWindow(Ex)にて、COMBOBOXクラスで作成すればよい。作成方法が違うだけで、他の操作はほぼ同様である。基本的には空のコンボボックスを作成し、CB_ADDSTRINGメッセージで選択肢を追加,CB_SETCURSELメッセージにて、デフォルトの選択位置を設定すればよい。尚、選択結果については、CB_GETCURSELメッセージにて、取得する事が出来る。この結果は、選択された番号,(0〜)で返されるが、ユーザが編集している場合は、−1が返されるので、編集結果は、GetWindowText等で受け取る事になる。

  • ステータスバー
    ステータスバーとは、これを見ているブラウザにも付いていると思うが、ウインドウの下の方に付いてる灰色の部分だ。この辺は、当然知ってると考えて話を進めよう。ステータスバーとか、次に説明するツールバーについては、コモン・コントロールと呼ばれるらしい。commctrl.hをインクルードしなければならない事と、造る前に、必ず、InitCommonControls()関数(引数は無いので、メインウインドウ開いた後にでも呼んでおけば良い)を呼ばなければならない事以外、両者共、ボタンや、エディットコントロールと同様に、ウインドウの一種と考えて良いだろう。即ち、CreateWindowEx()で作成出来なくも無い。(因みに、CreateWindowExを使用する場合は、クラス名の指定を、STATUSCLASSNAMEとすると、ステータスバー,TOOLBARCLASSNAMEとすれば、ツールバーが作成される。) ただ、特にツールバーの場合は、結果的に、色々と設定を追加しなければならないので、専用の関数、CreateStatusWindow,CreateToolbarExが有るので、これを利用した方が良いだろう。これらは、結果的に、CreateWindowEx関数を呼んでくれて(のだと思う)、結果としては同じものが得られる。さて、細かく説明すると、長くなってしまうので、詳細は、サンプルをみて試して貰えば良いとして、特記事項となるポイントだけ、簡潔に述べておく。

    • コモンコントロールの下準備をする事(commctrl.h,InitCommonControls())

    • 作成時のスタイルに、SBARS_SIZEGRIPを追加すると、ステータスバーの右端に、サイズグリップが付く(3本の斜線)

    • 2つのタイプが有り、区切り目の無いシンプルタイプと、幾つかの部屋?に分かれたタイプが有る。シンプルタイプは、メッセージとして、SB_SIMPLEを送る事で定義する。シンプルタイプと、他のタイプでは、メッセージ表示のさせかた等が異なるので注意だ。

    • WM_SIZEの処理
      親Windowのサイズが変わる(WM_SIZE)時に、ステータスバーにもメッセージを送る必要が有る。この時、部屋を区切っている場合には、区切りの位置も指定し直す必要がある。

    • その他、ステータスバーに関するメッセージやスタイルには、頭にSBが付いているので、これを検索すると使い方が分かる。


  • ツールバー
    ステータスバーに比べて、ツールバーの方は準備が面倒なのである。自分で造る場合は、サイズを合わせてビットマップを造らなければならないし、変な構造体も使わなければならない。これで、CreateWindowExなど使ってたら、面倒臭くて頭がぶっ飛ぶのだ。幸い、自分は、事務的なツールが主なので、普通のボタンを並べれば済む的考え方で、ツールバーなど、あまり使う事が無いのだが、見栄えを気にする方や、良く使うという場合は、早めにマクロ化するなり、クラス化してしまった方が賢明なのだ。とにかく面倒臭い。
    そんな訳で、今回は、割と汎用に使える関数ライブラリにまとめてみた。要は、空のツールバーを作成して、そこに、予め、必要なビットマップをロードしておき、ボタンを追加していくという方法である。サイズは、自動で調整される様にした。幾つかのボタンを、生成時に組み込んでおく事も出来るが、サンプルの方法の方が、汎用的だと思う。因みに、ユーザがボタンの絵を用意する際は、1個1個別個に用意するのではなく、使う分だけ横並びに作成しておいて、ロードさせる時に、何個登録したいかを指定すれば良い。
    説明を付けたり、ツールチップを付けたりという小技については、また今度って事で…、ステータスバー同様に、ポイントだけ、説明する。

    • コモンコントロールの下準備をする事(commctrl.h,InitCommonControls())
      ※既にステータスバー等を作成しており、一度実施されていれば実施の必要は無い

    • 大きく分けて3種類
      ボタンは、大きく分けて3種類のタイプが有る。一つは、ユーザがビットマップを作成して取り込むタイプ。一つはスタンダードタイプのボタン(ファイルオープン,新規作成など),最後は、VIEWタイプ(親ディレクトリ,リスト表示など)のボタンである。スタンダードとVIEWのタイプには、SMALLとLARGEの指定が有る。

    • ボタンの追加手順
      1. 目的のボタンが入ったビットマップをロードする。TBLoadBitmap参照
        この時のインスタンスは、STDとVIEWの場合は、HINST_COMMCTRL,ユーザボタンならば、アプリのインスタンスを使う。既に同じビットマップがロードされていれば、その値が使える仕組みにした。

      2. ボタンを追加する。TBAddButton参照

      3. ボタンとボタンの間に間隔を空けるには、空のボタンを1個挿入する。

    • WM_SIZEの処理
      親Windowのサイズが変わる(WM_SIZE)時に、ツールバーにもメッセージを送る必要が有る。

    • その他、ステータスバーに関するメッセージやスタイルには、頭にTBが付いているので、これを検索すると使い方が分かる。


  • ラジオボタン
    時々使う場面のあるこいつである。作り方は簡単で、CreateWindow(Ex)にて、BUTTONを作成し、スタイルをBS_PUSHBUTTONでは無く、BS_RADIOBUTTONにすれば良い。オートマチックに、ON/OFFをコントロールしてくれるBS_AUTORADIOBUTTONというのも有るが、基本的な方を知っていた方が良いだろうと言うことで、今回は、手動?の方を使ってみた。基本的に、ON/OFFは、ユーザがコントロールするのであるが、操作は簡単で、ボタンがチェックされると、プッシュボタンと同じ様にイベントが上がるので、イベントが上がったボタンをON,それ以外をOFFにしてやれば良い。ON/OFFの表示制御は、BM_SETCHECKのBST_CHECKEDメッセージを送ればON,BM_SETCHECKのBST_UNCHECKEDメッセージを送ればOFFが表示される。

  • チェックボックス
    これも時々使う場面に出会うのだ。これもボタンなので、CreateWindow(Ex)にて、BUTTONを作成し、スタイルをBS_PUSHBUTTONでは無く、BS_CHECKBOXにすれば良い。これにもBS_AUTOCHECKBOXってのが有るが、ラジオボタンと同じ理由で手動を採用したので、ON/OFFは、ユーザが管理するのである。操作方法は、BM_GETCHECKメッセージにて、現在のスイッチ状態を取得し、これがBST_CHECKEDであれば、BST_UNCHECKEDの様に、逆を指定すれば良いのだ。(指定方法は、ラジオボタンと同様)

  • スクロールバー
    この辺はおまけなので、いいかげんな説明だが、詳しく説明していたら10ページ位になるかも…。そもそもスクロールバーを単独で使う場面はあまり無いのだが、いざ制御しようとすると、これは結構難しい。VC++とMFCで使った時は簡単だったから、簡単に出来るだろう?と思ったら、なかなか思った通りに動かなくて苦労してしまった。
    キモと思われるポイントについて、以下にまとめたので、サンプルを参照して確認してみてほしい。
    • 作成は簡単である。CreateWindowで、SCROLLBARクラスを指定すれば良い。
    • SCROLLINFO構造体の内、最低でもcbSizeと、nMax,nPageをセットして、スクロールバーに、SBM_SETSCROLLINFOメッセージを送って初期設定を行う。fMaskは、SIF_ALLとするのが望ましい。
    • スクロールバーの移動位置認知と、表示位置設定は、プログラマが行う。
      スクロールバーに変化が有った場合、親ウインドウに、WM_VSCROLL(縦方向のスクロールバーの場合)または、WM_HSCROLL(横方向のスクロールバーの場合)メッセージが上がる。移動情報は、wParamのLOWORDにセットされているので、この情報から、移動した距離を割り出して、SBM_SETSCROLLINFOメッセージにて表示位置を設定するのである。
    • 例えば、横スクロールバーが、同一Window内に2本存在した場合は、どうすれば良いのだろうか??当然、親Windowに上がる、WM_HSCROLLのメッセージは共有する事になるのだが、この時、lParamにスクロールバーのハンドルが設定されているので、HWND型にキャストして受け取れば、目的のスクロールバーに対してのみコントロール出来る訳である。更に、処理(SCROLLINFO構造体)も共用したければ、ハンドルを取得した後でGET_SCROLLINFOして、設定値を取り出し、移動情報を設定しなおして、SET_SCROLLINFOすれば良いという訳である。


  • ビットマップボタン
    これも時々使う場面に出会うのだ。ボタンが文字だけでは分かりにくい場合とか、特に目立たせたい場合だな。これもボタンなので、CreateWindow(Ex)にて、BUTTONを作成し、スタイルをBS_PUSHBUTTONでは無く、BS_BITMAPにすれば良い。BS_ICONというのも有るが、制御方法は殆ど同じなので、挑戦してみるのも良いだろう。作成したボタンに対して、画像をロードすれば、ボタンに表示してくれる。後は、普通のボタンと全く同じである。この他にも、BS_OWNERDRAWというタイプのボタンも有るのだが、こちらの方は、押す前のボタン画像と、ボタンを押した時の画像を別個に用意して、親ウインドウに、WM_DRAWITEMのメッセージが到着したら、画面上に表示する等という操作をしなければならないなど、複雑な操作を要するので、ちょっと後回しにした。

2002/05/18
HomeSweetHome2
Ozzy's Software