入力ボックスを作成する-ondraw – FlyWithLua

2023年2月27日

英数字をキーボードから入力でき、カーソルも表示、deleteキーでテキストも削除できる。float_wnd_set_ondrawなのだが、日本語が使えない。コピー&ペーストができない。

多分フォント指定で「Helvetica_12」を使っているから。日本語はフォントを指定したらだめ。

function PoloInput_get() でキーボードからの入力を取得。function gPoloInput_ondraw で入力ボックスを作成表示している。
function PoloInput_onclick()はクリックするために必要。103行目のfalseはその上で設定した範囲内をクリックした場合、赤色カーソルがボックスに出現。
trueにするとウインドウのどこでもクリックすると赤色のカーソルがボックスに出現する。
複数のボックスを作成する場合はfalseにしないと全部のボックスにカーソルが出現することになる。

-- ユーザー入力行の初期設定
local inputLine = { value = "", data = "", state = false, pos = 0, latlon = false, len = 0 }    --配列で初期設定している。
local PoloTest_wnd = nil -- ウインドウのハンドル、最初は空
local dWidth, dHeight = 0, 0 -- ウインドウの端と高さの起点

----------------------------------------------------------------------------
-- 入力行からユーザー入力データを取得する関数
function PoloInput_get()
    -- inputLine.state とは上の宣言文、inputLineのstateを使うということになる。つまり inputLine.state = false となる。
    if (inputLine.state and KEY_ACTION == "pressed") then   -- falseの状態でキーを押した時のアクション
        RESUME_KEY = true

        -- 27 = escape(このキーを使うとボックスそのものが消えてしまう)使ってはダメ
        if (VKEY == 27) then
            keyboard_focus_reset()
            RESUME_KEY = false
            return
        end
        -- 8 = delete(このキーを使って入力した文字を削除することができる)8=BackSpaceキー(Windows)
        if (VKEY == 8) then
            if (inputLine.data ~= "") then --空文字でない場合
                --string.subは入力されたinputLine.dataの1つ目を選択、文字の長さを取得して、カーソルは1つ後なので -1で1字戻って最後の文字までを選択することになる
                --簡単に言うとこれが入力された文字を全て選択した状態になる。
                inputLine.data = string.sub(inputLine.data, 1, string.len(inputLine.data) - 1)
            else
                inputLine.data = ""
            end

            inputLine.value = inputLine.data

            return
        end
        -- enter(このキーを使って入力した文字を消すことができる)13=←キー
        if (VKEY == 13) then
            inputLine.data = "" --空文字にする
            inputLine.state = false --エンターキーでボックスを入力不可にする(ボックスクリックで可能になる)
            return
        end
        -- 他に何か
        --inputLine.data = string.upper(inputLine.data) .. string.upper(CKEY)--string.upperは大文字に変換
        --inputLine.data = string.lower(inputLine.data) .. string.lower(CKEY)--string.lowerは大文字に変換
        inputLine.data = tostring(inputLine.data) .. tostring(CKEY) --キーで選択した大文字、小文字通りを表示する
        inputLine.value = inputLine.data

        -- ドル記号($)はラトロン(緯度経度)を示します
        if (string.find(inputLine.value, "%$") ~= nil) then inputLine.latlon = true end
    end
end

--ウインドウ内の描画関数-------------------------------------------------------------------------------
-- float_wnd_set_ondraw()の関数
-- xとyはウィンドウの原点、つまり左下です。xは右に増加し、yは上に増加します。
function gPoloInput_ondraw(PoloTest_wnd, x, y)
    -- returns window size
    dWidth, dHeight = float_wnd_get_dimensions(PoloTest_wnd)

    -- draw box around window
    XPLMSetGraphicsState(0, 0, 0, 1, 1, 0, 0)

    --重要 テキストボックス作成----------------------------------------------------------------
    -- データ入力領域を描画します
    glColor4f(1, 1, 1, 0.25) -- gray background
    glRectf(x + 28, y + dHeight - 24, x + 165, y + dHeight - 9) --dHeightによって上が基準、これが無いと下が基準になる

    glColor4f(1, 1, 1, 1) -- white text
    -- inputLine.dataのグラフィカルな長さに基づいて文字数を制限する
    if (measure_string(inputLine.data, "Helvetica_12") < 139) then --measure=測定、inputLine.data=入力された文字列を数え、139より小さくする
        inputLine.len = string.len(inputLine.data)
    end

    --ボックス内のテキスト書体
    --string.subには入力された文字烈が入る
    draw_string_Helvetica_12(x + 30, y + dHeight - 21, string.sub(inputLine.data, 1, inputLine.len))

    glColor4f(1, 0, 0, 1) -- 左端のマゼンタカーソル色
    glBegin_LINES() --ラインを描画
    if (inputLine.state) then --入力ラインをクリックされたら
        local cursize = measure_string(inputLine.data, "Helvetica_12") --measure=測定、inputLine.data=入力された文字列
        --cursizeは文字列をバイト数(英語は1文字 1バイト)
        if (cursize > 137) then
            cursize = 137 --文字数の制限
        end
        inputLine.pos = x + 30 + cursize --カーソル入力ラインの表示位置、最後のcursizeは文字数が増えるのでカーソル位置が移動する
        glVertex2f(inputLine.pos, y + dHeight - 9) --縦長カーソルの上の位置
        glVertex2f(inputLine.pos, y + dHeight - 24) --縦長カーソルの下の位置
    end
    glEnd() --OpenGL Graphicsの最後に入れる


    draw_string(x + 30, y + 10, inputLine.value, 0, 1, 0) --入力された文字列をウインドウのどこかに表示
end -- function gPoloInput_ondraw
-----------------------------------------------------------------------------------------------------

--クリック動作-----------------------------------------------------------------------------------------
--float_wnd_set_onclick()の関数
--xとyは、ウィンドウの原点、つまり左下からの相対値です。state:1 =マウスを下にクリック、2 =マウスをドラッグ、3 =マウスを上に
function PoloInput_onclick(PoloTest_wnd, x, y, state)
    -- state=1 はボタンダウンのクリックイベント
    if (state == 1) then
        if (x >= 28 and x <= 165 and y >= dHeight - 24 and y <= dHeight - 9) then --カーソル表示のクリック範囲(ウインドウ内)
            inputLine.state = true --入力ができる状態
        else
            inputLine.state = true --false、上の範囲以外をクリックした場合入力できない。trueにするとウインドウのどこかをクリックすると入力できる。
        end
    end
end -- function PoloInput_onclick

--クリック動作-----------------------END---------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-- window close
function PoloInput_onclose(PoloTest_wnd)
    float_wnd_destroy(PoloTest_wnd) --ウインドウを閉じる(destroy=無くす)
end

-- ウィンドウとサポートメソッドを作成する
PoloTest_wnd = float_wnd_create(200, 100, 1, true)
float_wnd_set_title(PoloTest_wnd, "Input Box")
float_wnd_set_position(PoloTest_wnd, 180, 150)
float_wnd_set_ondraw(PoloTest_wnd, "gPoloInput_ondraw")
float_wnd_set_onclick(PoloTest_wnd, "PoloInput_onclick")
float_wnd_set_onclose(PoloTest_wnd, "PoloInput_onclose")

-- ユーザー入力データを取得するためのもの(必須)
do_on_keystroke("PoloInput_get()")

リターンキーで入力したテキストを表示

上と違って、テキスト入力後、リターン(Mac?)キーで下に文字を(表示出力)する。
入力時は下にテキストは表示されない。表示されたときがリターンキーを押した時になる。

34行目の「VKEY == 13」と90行目の設定が上と違っている。これによりリターンキーを押すと入力された文字が下に表示されることになる。どこか別のところに出力するのに役に立つかも。

-- ユーザー入力行の初期設定
local inputLine = { value = "", data = "", state = false, pos = 0, latlon = false, len = 0 } --配列で初期設定している。
local PoloTest_wnd = nil -- ウインドウのハンドル、最初は空
local dWidth, dHeight = 0, 0 -- ウインドウの端と高さの起点

----------------------------------------------------------------------------
-- 入力行からユーザー入力データを取得する関数
function PoloInput_get()
    -- inputLine.state とは上の宣言文、inputLineのstateを使うということになる。つまり inputLine.state = false となる。
    if (inputLine.state and KEY_ACTION == "pressed") then -- falseの状態でキーを押した時のアクション
        RESUME_KEY = true

        -- 27 = escape(このキーを使うとボックスそのものが消えてしまう)使ってはダメ
        if (VKEY == 27) then
            keyboard_focus_reset()
            RESUME_KEY = false
            return
        end
        -- 8 = delete(このキーを使って入力した文字を削除することができる)8=BackSpaceキー(Windows)
        if (VKEY == 8) then
            if (inputLine.data ~= "") then --空文字でない場合
                --string.subは入力されたinputLine.dataの1つ目を選択、文字の長さを取得して、カーソルは1つ後なので -1で1字戻って最後の文字までを選択することになる
                --簡単に言うとこれが入力された文字を全て選択した状態になる。
                inputLine.data = string.sub(inputLine.data, 1, string.len(inputLine.data) - 1)
            else
                inputLine.data = ""
            end

            inputLine.value = inputLine.data

            return
        end
        -- enter(このキーを使って入力した文字を消すことができる)13=←キー
        if (VKEY == 13) then
            --inputLine.data = "" --空文字にする
            inputLine.data = inputLine.data --これでもいい?テキストを残す
            return
        end
        -- 他に何か
        --inputLine.data = string.upper(inputLine.data) .. string.upper(CKEY)--string.upperは大文字に変換
        --inputLine.data = string.lower(inputLine.data) .. string.lower(CKEY)--string.lowerは大文字に変換
        inputLine.data = tostring(inputLine.data) .. tostring(CKEY) --キーで選択した大文字、小文字通りを表示する
        inputLine.value = inputLine.data

        -- ドル記号($)はラトロン(緯度経度)を示します
        if (string.find(inputLine.value, "%$") ~= nil) then inputLine.latlon = true end
    end
end

--ウインドウ内の描画関数-------------------------------------------------------------------------------
-- float_wnd_set_ondraw()の関数
-- xとyはウィンドウの原点、つまり左下です。xは右に増加し、yは上に増加します。
function gPoloInput_ondraw(PoloTest_wnd, x, y)
    -- returns window size
    dWidth, dHeight = float_wnd_get_dimensions(PoloTest_wnd)

    -- draw box around window
    XPLMSetGraphicsState(0, 0, 0, 1, 1, 0, 0)

    --重要 テキストボックス作成----------------------------------------------------------------
    -- データ入力領域を描画します
    glColor4f(1, 1, 1, 0.25) -- gray background
    glRectf(x + 28, y + dHeight - 24, x + 165, y + dHeight - 9) --dHeightによって上が基準、これが無いと下が基準になる

    glColor4f(1, 1, 1, 1) -- white text
    -- inputLine.dataのグラフィカルな長さに基づいて文字数を制限する
    if (measure_string(inputLine.data, "Helvetica_12") < 139) then --measure=測定、inputLine.data=入力された文字列を数え、139より小さくする
        inputLine.len = string.len(inputLine.data)
    end

    --ボックス内のテキスト書体
    --string.subには入力された文字烈が入る
    draw_string_Helvetica_12(x + 30, y + dHeight - 21, string.sub(inputLine.data, 1, inputLine.len))

    glColor4f(1, 0, 0, 1) -- 左端のマゼンタカーソル色
    glBegin_LINES() --ラインを描画
    if (inputLine.state) then --入力ラインをクリックされたら
        local cursize = measure_string(inputLine.data, "Helvetica_12") --measure=測定、inputLine.data=入力された文字列
        --cursizeは文字列をバイト数(英語は1文字 1バイト)
        if (cursize > 137) then
            cursize = 137 --文字数の制限
        end
        inputLine.pos = x + 30 + cursize --カーソル入力ラインの表示位置、最後のcursizeは文字数が増えるのでカーソル位置が移動する
        glVertex2f(inputLine.pos, y + dHeight - 9) --縦長カーソルの上の位置
        glVertex2f(inputLine.pos, y + dHeight - 24) --縦長カーソルの下の位置
    end
    glEnd() --OpenGL Graphicsの最後に入れる

    --入力されたテキストをボックスの外に表示(但しリターンキーを押した時に表示)
    if (VKEY == 13) then    --13はリターンキー(Mac?)
        draw_string(x + 30, y + 10, inputLine.value, 0, 1, 0) --入力された文字列をウインドウのどこかに表示
    end
end -- function gPoloInput_ondraw

-----------------------------------------------------------------------------------------------------

--クリック動作-----------------------------------------------------------------------------------------
--float_wnd_set_onclick()の関数
--xとyは、ウィンドウの原点、つまり左下からの相対値です。state:1 =マウスを下にクリック、2 =マウスをドラッグ、3 =マウスを上に
function PoloInput_onclick(PoloTest_wnd, x, y, state)
    -- state=1 はボタンダウンのクリックイベント
    if (state == 1) then
        if (x >= 28 and x <= 165 and y >= dHeight - 24 and y <= dHeight - 9) then --カーソル表示のクリック範囲(ウインドウ内)
            inputLine.state = true --入力ができる状態
        else
            inputLine.state = false --false、上の範囲以外をクリックした場合入力できない。trueにするとウインドウのどこかをクリックすると入力できる。
        end
    end
end -- function PoloInput_onclick

--クリック動作-----------------------END---------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-- window close
function PoloInput_onclose(PoloTest_wnd)
    float_wnd_destroy(PoloTest_wnd) --ウインドウを閉じる(destroy=無くす)
end

-- ウィンドウとサポートメソッドを作成する
PoloTest_wnd = float_wnd_create(200, 100, 1, true)
float_wnd_set_title(PoloTest_wnd, "Input Box")
float_wnd_set_position(PoloTest_wnd, 180, 150)
float_wnd_set_ondraw(PoloTest_wnd, "gPoloInput_ondraw")
float_wnd_set_onclick(PoloTest_wnd, "PoloInput_onclick")
float_wnd_set_onclose(PoloTest_wnd, "PoloInput_onclose")

-- ユーザー入力データを取得するためのもの(必須)
do_on_keystroke("PoloInput_get()")

残念ながら、日本語が使えない、リターンキーで改行しての入力ができない。というより方法がわからないのかも。