Akira's Commentary


ビットマップのロード

ビットマップの準備ができたら、それをプログラムにロードしましょう。 ビットマップをプログラム上に取り込むにはいくつかの方法がありますが、 特定のビットマップだけを取り込む場合には、リソースとして定義して

hbm = GpiLoadBitmap(hps, NULLHANDLE, ID_BITMAP, 0, 0) ;

でロードするのが一番簡単でしょう。

リソースとして定義するには、リソースファイルに以下のように記述します。 ついでにアイコンも登録しておきます。

---- romy.rc ここから ----
/*
 * romy.rc - resource for Mr. Romy Watches You
 */

#include <os2.h>
#include "romyres.h"

ICON    ID_ROMY         romy.ico
BITMAP  ID_BITMAP       romy.bmp
---- romy.rc ここまで ----

ビットマップを操作(ロード)するには、 PS(プレゼンテーションスペース)を経由する必要があります。 シェイプウィンドウもシェイプの定義、 描画のためにメモリPSを使います。 そこで、ビットマップのロード、(目玉の)描画用に 専用のメモリPSを用意することにします。

メモリPSはメモリDC(デバイスコンテキスト)上に作成され、 メモリPSにはビットマップをロードして関連付けますので、 ビットマップに関連して 以下の3変数(ハンドル)を使うことになります。

HDC     hdcBitmap ;         デバイスコンテキスト
HPS     hpsBitmap ;         プレゼンテーションスペース
HBITMAP hbmBitmap ;         ビットマップ

これらの33変数は、 ビットマップのロード関数で生成することにします。 生成する関数を用意したなら、 開放する関数もいっしょに作っておきます。

これらの資源はプログラム(プロセス)終了時に 自動的に開放されますが、 生成/開放関数を対で作って ちゃんと開放するようにしておいた方がいいでしょう。

ビットマップのロード/開放関数は以下のようなものになります。 このあたりも約束事みたいなものです。

---- ビットマップのロード/開放関数 ここから ----
/*
 * load/free Bitmap
 */

HDC     hdcBitmap = NULLHANDLE ;
HPS     hpsBitmap = NULLHANDLE ;
HBITMAP hbmBitmap = NULLHANDLE ;

static  void    loadBitmap(HAB hab)
{
    SIZEL   siz ;
    
    hdcBitmap =DevOpenDC(hab, OD_MEMORY, "*", 0, NULL, NULLHANDLE) ;
    siz.cx = siz.cy = 0 ;
    hpsBitmap = GpiCreatePS(hab, hdcBitmap, &siz,
            PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC) ;
    if (hdcBitmap == NULLHANDLE || hpsBitmap == NULLHANDLE) {
        return ;
    }
 
    hbmBitmap = GpiLoadBitmap(hpsBitmap, NULLHANDLE, ID_BITMAP, 0, 0) ;
    GpiSetBitmap(hpsBitmap, hbmBitmap) ;
}

static  void    freeBitmap(void)
{
    if (hbmBitmap != NULLHANDLE) {
        GpiDeleteBitmap(hbmBitmap) ;
	hbmBitmap = NULLHANDLE ;
    }
    if (hpsBitmap != NULLHANDLE) {
        GpiDestroyPS(hpsBitmap) ;
	hpsBitmap = NULLHANDLE ;
    }
    if (hdcBitmap != NULLHANDLE) {
        DevCloseDC(hdcBitmap) ;
	hdcBitmap = NULLHANDLE ;
    }
}
---- ビットマップのロード/開放関数 ここまで ----

このビットマップロード関数を呼び出せば、 メモリPS上にビットマップの絵が描画されます。 とりあえず、メイン関数に組み込んでおきましょう。 メイン関数は以下のようになります。

念のため: この段階でもまだ動作しません。ですが、 メッセージループをコメントアウトして、 初期化(ビットマップロード)が正常に実行されるかどうかを 試してみるといいかもしれません。 といっても、メッセージボックスでエラーがでなければ うまくいった、というレベルですので、 あまり面白いものではありませんが。

---- メイン関数 ここから ----
/*
 * main - program start here
 */

int     main(int ac, char *av[])
{
    HAB     hab  ;
    HMQ     hmq  ;
    QMSG    qmsg ;
    
    myname(av[0]) ;
    _wildcard(&ac, &av) ;

    hab = WinInitialize(0) ;
    hmq = WinCreateMsgQueue(hab, 0) ;
    
    loadBitmap(hab) ;
     
    if (hbmBitmap == NULLHANDLE) {
        trMessage("failed to load bitmap") ;
        freeBitmap() ;
        WinDestroyMsgQueue(hmq) ;
        WinTerminate(hab) ;
 	return 1 ;
    }

    /*
     * Start Window Processing
     */

    while (WinGetMsg(hab, &qmsg, 0, 0, 0)) {
        WinDispatchMsg(hab, &qmsg) ;
    }

    /*
     * dispose resources
     */

    freeBitmap() ;
    
    WinDestroyMsgQueue(hmq) ;
    WinTerminate(hab) ;
    
    return 0 ; 
}
---- メイン関数 ここまで ----