可変オブジェクト設置モジュール

新しい差分ファイル作成ツールやランチャー制作ツールの UI では、可変サイズのウィンドウで、サイズ変更に伴ってオブジェクトの位置やサイズも変わる形にしようと考えています。そこで、可変オブジェクトの設置がなるべく簡単になるように、モジュールを作りました。

位置やサイズを固定部分(ピクセル)と可変部分(ウィンドウのサイズとの割合)に分けて指定します。サンプルもあります。ちょっとした UI を実現させるためにちょっと長くなってしまいましたが。まだまだ改良の余地はありそうです。

モジュール部分

#ifndef __MOD_OBJPOSMAN__
#define __MOD_OBJPOSMAN__

#include "user32.as"

// オブジェクトの位置やサイズを管理するモジュール
#module modObjPosMan

    #const MAX_OBJECT 64                // 一つのスクリーンで管理するオブジェクトの最大個数
    #const MAX_SCREEN 16                // 管理するスクリーンの最大個数

    #enum SFX_POSX_FIXED = 0            // 位置のX座標 の固定部分 の添え字番号
    #enum SFX_POSX_LIQUID               // 位置のX座標 の可変部分 の添え字番号
    #enum SFX_POSY_FIXED                // 位置のY座標 の固定部分 の添え字番号
    #enum SFX_POSY_LIQUID               // 位置のY座標 の可変部分 の添え字番号
    #enum SFX_WIDTH_FIXED               // 幅 の固定部分 の添え字番号
    #enum SFX_WIDTH_LIQUID              // 幅 の可変部分 の添え字番号
    #enum SFX_HEIGHT_FIXED              // 高さ の固定部分 の添え字番号
    #enum SFX_HEIGHT_LIQUID             // 高さ の可変部分 の添え字番号
    #enum MAX_SFX                       // 要素数

    // 初期化
    #deffunc InitObjPosMan
        dim ObjectPosSize, MAX_SFX, MAX_OBJECT, MAX_SCREEN   // オブジェクトの位置やサイズ
        dim ManageWndIdTbl, MAX_SCREEN                       // 管理するウィンドウのIDのテーブル
        nManageWnd = 0                                       // 管理するウィンドウの数
        dim ManageObjIdTbl, MAX_OBJECT, MAX_SCREEN           // 管理するオブジェクトのID
        dim nManageObj, MAX_SCREEN                           // 管理するオブジェクトの数
        dim IsSetOncmd, MAX_SCREEN                           // WM_SIZE の飛び先を設定したか

        return

    // ウィンドウの管理用通し番号を取得
    //     GetWndSerno( (ウィンドウID) )
    //     ウィンドウの管理用通し番号を返す
    #defcfunc GetWndSerno int WndId, \
    local serno
        serno = -1
        // 線形探索
        repeat nManageWnd
            if ManageWndIdTbl( cnt ) == WndId {
                serno = cnt
                break
            }
        loop
        if serno == -1 {
            ManageWndIdTbl( nManageWnd ) = WndId
            serno = nManageWnd
            nManageWnd ++
        }
        return serno

    // オブジェクトの管理用通し番号を取得
    //     GetObjSerno( (ウィンドウの管理用通し番号), (オブジェクトID) )
    //     オブジェクトの管理用通し番号を返す
    #defcfunc GetObjSerno int WndSerno, int ObjId, \
    local serno
        serno = -1
        // 線形探索
        repeat nManageObj( WndSerno )
            if ManageObjIdTbl( cnt, WndSerno ) == ObjId {
                serno = cnt
                break
            }
        loop
        if serno == -1 {
            ManageObjIdTbl( nManageObj( WndSerno ), WndSerno ) = ObjId
            serno = nManageObj( WndSerno )
            nManageObj( WndSerno ) ++
        }
        return serno

    // オブジェクトの位置・サイズを変更( フラグ1: 位置変更 フラグ2: サイズ変更 )
    //     MoveObj (オブジェクトID), (フラグ)
    //     フラグ: 1 = 位置変更
    //              2 = サイズ変更
    #deffunc MoveObj int ObjId, int flag, \
    local WndSerno, local ObjSerno, local hObj, \
    local rect, local hParentWnd, local x, local y, local w, local h
        WndSerno = GetWndSerno( ginfo_sel )
        ObjSerno = GetObjSerno( WndSerno, ObjId )
        hObj = objinfo( ObjId, 2 )
        
        dim rect, 4
        GetWindowRect hObj, varptr( rect )
        GetParent hObj : hParentWnd = stat
        MapWindowPoints 0, hParentWnd, varptr( rect ), 2
        x = rect( 0 )
        y = rect( 1 )
        w = rect( 2 ) - rect( 0 )
        h = rect( 3 ) - rect( 1 )

        if ( flag & 1 ) != 0 {
            x  = ObjectPosSize( SFX_POSX_FIXED    , ObjSerno, WndSerno )
            y  = ObjectPosSize( SFX_POSY_FIXED    , ObjSerno, WndSerno )
            x += ObjectPosSize( SFX_POSX_LIQUID   , ObjSerno, WndSerno ) * ginfo_winx / 10000
            y += ObjectPosSize( SFX_POSY_LIQUID   , ObjSerno, WndSerno ) * ginfo_winy / 10000
        }

        if ( flag & 2 ) != 0 {
            w  = ObjectPosSize( SFX_WIDTH_FIXED   , ObjSerno, WndSerno )
            h  = ObjectPosSize( SFX_HEIGHT_FIXED  , ObjSerno, WndSerno )
            w += ObjectPosSize( SFX_WIDTH_LIQUID  , ObjSerno, WndSerno ) * ginfo_winx / 10000
            h += ObjectPosSize( SFX_HEIGHT_LIQUID , ObjSerno, WndSerno ) * ginfo_winy / 10000
        }

        MoveWindow hObj, x, y, w, h, 1
        return

    // オブジェクトの位置を指定
    //     SetObjPos (オブジェクトID), (固定X座標), (可変X座標), (固定Y座標), (可変Y座標)
    //     可変部分はウィンドウのクライアントエリアの大きさとの割合で、10000を最大とする。
    #deffunc SetObjPos  int ObjId, int _PosXFixed, int _PosXLiquid, int _PosYFixed, int _PosYLiquid, \
    local WndSerno, local ObjSerno
    
        WndSerno = GetWndSerno( ginfo_sel )
        ObjSerno = GetObjSerno( WndSerno, ObjId )

        if IsSetOncmd( WndSerno ) == 0 {
            IsSetOncmd( WndSerno ) = 1
            oncmd gosub *l_Resize, $0005    // WM_SIZE
        }

        ObjectPosSize( SFX_POSX_FIXED    , ObjSerno, WndSerno ) = _PosXFixed
        ObjectPosSize( SFX_POSX_LIQUID   , ObjSerno, WndSerno ) = _PosXLiquid
        ObjectPosSize( SFX_POSY_FIXED    , ObjSerno, WndSerno ) = _PosYFixed
        ObjectPosSize( SFX_POSY_LIQUID   , ObjSerno, WndSerno ) = _PosYLiquid

        MoveObj ObjId, 1
        return
    // オブジェクトのサイズを指定
    //     SetObjSize (オブジェクトID), (固定幅), (可変幅), (固定高さ), (可変高さ)
    //     可変部分はウィンドウのクライアントエリアの大きさとの割合で、10000を最大とする。
    #deffunc SetObjSize int ObjId, int _WidthFixed, int _WidthLiquid, int _HeightFixed, int _HeightLiquid, \
    local WndSerno, local ObjSerno
        WndSerno = GetWndSerno( ginfo_sel )
        ObjSerno = GetObjSerno( WndSerno, ObjId )

        if IsSetOncmd( WndSerno ) == 0 {
            IsSetOncmd( WndSerno ) = 1
            oncmd gosub *l_Resize, $0005    // WM_SIZE
        }

        ObjectPosSize( SFX_WIDTH_FIXED   , ObjSerno, WndSerno ) = _WidthFixed
        ObjectPosSize( SFX_WIDTH_LIQUID  , ObjSerno, WndSerno ) = _WidthLiquid
        ObjectPosSize( SFX_HEIGHT_FIXED  , ObjSerno, WndSerno ) = _HeightFixed
        ObjectPosSize( SFX_HEIGHT_LIQUID , ObjSerno, WndSerno ) = _HeightLiquid

        MoveObj ObjId, 2
        return
    // ウィンドウ内の全オブジェクトの位置とサイズの変更
    #deffunc Resize int WndId, \
    local SelWndId, local WndSerno
        SelWndId = ginfo_sel : gsel WndId
        WndSerno = GetWndSerno( WndId )
        repeat nManageObj( WndSerno )
            MoveObj ManageObjIdTbl( cnt, WndSerno ), 3
        loop
        gsel SelWndId
        return
*l_Resize
    Resize ginfo_intid
    return
#global
InitObjPosMan
#endif

MoveObj の命令定義内の、

repeat 2
    ScreenToClient hParentWnd, varptr( rect( cnt * 2 ) )
loop

となっていた部分を以下のように変更しました。

MapWindowPoints 0, hParentWnd, varptr( rect ), 2

どちらでも、やっていることは同じです。この MapWindowPoints API は ScreenToClient API や、 ClientToScreen API の拡張版みたいなもののようですね。

サンプル

#include "user32.as"
#include "gdi32.as"

screen 0, ginfo_dispx, ginfo_dispy, 2
    GetWindowLong hwnd, -16
    SetWindowLong hwnd, -16, stat | $50000    // WS_MAXIMIZEBOX | WS_SIZEBOX
    width 480, 320
    
    // ステータスバー
        winobj "msctls_statusbar32", "", , $50000000    // WS_VISIBLE | WS_CHILD
        ObjId = stat
        //ステータスバーの高さを得る
        dim RectStatusBar, 4
        GetWindowRect objinfo( ObjId, 2 ), varptr( RectStatusBar )
        StatusBarHeight = RectStatusBar.3 - RectStatusBar.1
        
        SetObjPos  ObjId, 0, 0, -StatusBarHeight, 10000
        SetObjSize ObjId, 0, 10000, StatusBarHeight, 0
    
    // 複数行エディットボックス
        sdim mesboxBuf : mesboxBuf = "複数行エディットボックス"
        mesbox mesboxBuf
        ObjId = stat
        SetObjPos  ObjId, 0, 0, 0, 0
        SetObjSize ObjId, 0, 10000, -StatusBarHeight, 10000
    
        gsel ginfo_sel, 1

#const MARGIN_TOP             10
#const MARGIN_LEFT            15
#const MARGIN_BOTTOM          10
#const MARGIN_RIGHT           15

#const BUTTON_WIDTH           72
#const BUTTON_HEIGHT          20

#const SPACE_SIZE              4

#const WINDOW_MIN_WIDTH      MARGIN_LEFT + MARGIN_RIGHT + BUTTON_WIDTH * 4 + SPACE_SIZE * ( 4 - 1 )
#const WINDOW_MIN_HEIGHT     MARGIN_TOP + BUTTON_HEIGHT * ( 4 + 3 + 1 ) + SPACE_SIZE * ( 4 - 1 ) + MARGIN_BOTTOM

screen 2, ginfo_dispx, ginfo_dispy, 2
    GetWindowLong hwnd, -16
    SetWindowLong hwnd, -16, stat | $50000    // WS_MAXIMIZEBOX | WS_SIZEBOX
    width WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT
    GetStockObject 17 : hDefaultGUIFont = stat
    oncmd gosub *minmaxinfo, $0024    // WM_MINMAXINFO

    syscolor 15 : boxf

    winobj "static", "ファイル:", 0, $50000002    // WS_VISIBLE | WS_CHILD | SS_RIGHT
    ObjId = stat
    SetObjPos  ObjId, MARGIN_LEFT, 0, MARGIN_TOP, 0
    SetObjSize ObjId, BUTTON_WIDTH, 0, BUTTON_HEIGHT, 0
    sendmsg objinfo( ObjId, 2 ), $0030, hDefaultGUIFont, 1    // WM_SETFONT

    sdim dummyStr
    input dummyStr
    ObjId = stat
    SetObjPos  ObjId, MARGIN_LEFT + BUTTON_WIDTH + SPACE_SIZE, 0, MARGIN_TOP, 0
    SetObjSize ObjId, -( MARGIN_LEFT + ( BUTTON_WIDTH + SPACE_SIZE ) * 2 + MARGIN_RIGHT ), 10000, BUTTON_HEIGHT, 0

    button gosub "参照", *dummyLabel
    ObjId = stat
    SetObjPos  ObjId, -( MARGIN_LEFT + BUTTON_WIDTH ), 10000, MARGIN_TOP, 0
    SetObjSize ObjId, BUTTON_WIDTH, 0, BUTTON_HEIGHT, 0

    winobj "static", "オプション:", 0, $50000002    // WS_VISIBLE | WS_CHILD | SS_RIGHT
    ObjId = stat
    SetObjPos  ObjId, MARGIN_LEFT, 0, MARGIN_TOP + BUTTON_HEIGHT + SPACE_SIZE, 0
    SetObjSize ObjId, BUTTON_WIDTH, 0, BUTTON_HEIGHT, 0
    sendmsg objinfo( ObjId, 2 ), $0030, hDefaultGUIFont, 1    // WM_SETFONT

    repeat 3
        chkbox strf("%c", 'A'+cnt), dummyInt
        ObjId = stat
        SetObjPos  ObjId, MARGIN_LEFT + BUTTON_WIDTH + SPACE_SIZE, 0, MARGIN_TOP + ( BUTTON_HEIGHT + SPACE_SIZE ) * ( cnt + 1 ), 0
        SetObjSize ObjId, -( MARGIN_LEFT + BUTTON_WIDTH + SPACE_SIZE + SPACE_SIZE / 2 ), 5000, BUTTON_HEIGHT, 0
    loop

    winobj "static", "モード:", 0, $50000002    // WS_VISIBLE | WS_CHILD | SS_RIGHT
    ObjId = stat
    SetObjPos  ObjId, MARGIN_LEFT, 0, MARGIN_TOP + ( BUTTON_HEIGHT + SPACE_SIZE ) * 4, 0
    SetObjSize ObjId, BUTTON_WIDTH, 0, BUTTON_HEIGHT, 0
    sendmsg objinfo( ObjId, 2 ), $0030, hDefaultGUIFont, 1    // WM_SETFONT

    listbox dummyInt,, "Apple\nOrange\nGrape"
    ObjId = stat
    SetObjPos  ObjId, MARGIN_LEFT + BUTTON_WIDTH + SPACE_SIZE, 0, MARGIN_TOP + ( BUTTON_HEIGHT + SPACE_SIZE ) * 4, 0
    SetObjSize ObjId, -( MARGIN_LEFT + BUTTON_WIDTH + SPACE_SIZE + SPACE_SIZE / 2 ), 5000, BUTTON_HEIGHT * 3, 0

    winobj "static", "ログ:", 0, $50000000    // WS_VISIBLE | WS_CHILD
    ObjId = stat
    SetObjPos  ObjId, SPACE_SIZE / 2, 5000, MARGIN_TOP + BUTTON_HEIGHT + SPACE_SIZE, 0
    SetObjSize ObjId, -( SPACE_SIZE / 2 + MARGIN_RIGHT ), 5000, BUTTON_HEIGHT, 0
    sendmsg objinfo( ObjId, 2 ), $0030, hDefaultGUIFont, 1    // WM_SETFONT

    mesbox dummyStr
    ObjId = stat
    SetObjPos  ObjId, SPACE_SIZE / 2, 5000, MARGIN_TOP + ( BUTTON_HEIGHT + SPACE_SIZE ) * 2, 0
    SetObjSize ObjId, -( SPACE_SIZE / 2 + MARGIN_RIGHT ), 5000, -( MARGIN_TOP + ( BUTTON_HEIGHT + SPACE_SIZE ) * 2 + MARGIN_BOTTOM + BUTTON_HEIGHT + SPACE_SIZE ), 10000

    button gosub "OK", *dummyLabel
    ObjId = stat
    SetObjPos  ObjId, -( MARGIN_RIGHT + BUTTON_WIDTH * 2 + SPACE_SIZE ), 10000, -( MARGIN_BOTTOM + BUTTON_HEIGHT ), 10000
    SetObjSize ObjId, BUTTON_WIDTH, 0, BUTTON_HEIGHT, 0
    button gosub "キャンセル", *dummyLabel
    ObjId = stat
    SetObjPos  ObjId, -( MARGIN_RIGHT + BUTTON_WIDTH ), 10000, -( MARGIN_BOTTOM + BUTTON_HEIGHT ), 10000
    SetObjSize ObjId, BUTTON_WIDTH, 0, BUTTON_HEIGHT, 0

    gsel ginfo_sel, 1

stop

*dummyLabel
    return

*minmaxinfo
    dupptr mmi, lParam, 40
    mmi(6) = WINDOW_MIN_WIDTH  + ( ginfo_sizex - ginfo_winx )
    mmi(7) = WINDOW_MIN_HEIGHT + ( ginfo_sizey - ginfo_winy )
    return

インフォメーション

公開日時
2007年7月11日 午後7時12分0秒
最終更新日時
2007年12月19日 午後10時25分23秒
カテゴリ
HSP