TextCtr のフォーカスがオン・オフになったとき背景色を動的に変化させる(wxHaskell)

  • TAB キーでTextCtrlを移動してフォーカスがON、OFFになたとき、または、マウスでTextCtrlを選択してフォーカスがON、OFFになたときに背景色を変化させたい。


現在どの wxTextCtrl に入力しているか明確にするために、フォーカスがオンになっている wxTextCtrl の背景色を変更させたいと考え、TextCtrlの textCtrlGetDefaultStyle、textCtrlSetDefaultStyle、textAttrGetBackgroundColour、textAttrSetBackgroundColourを使用してみました。
ところが、これは入力したテキストの背景色を設定するもので、wxTextCtrlの背景色そのものは変化しません。
Windowの windowSetBackgroundColour を使用することでフォーカスがオンになっている wxTextCtrl の背景色を動的に変化させることができました。

  • wxFormBuilder

まず、wxFormBuilder でフォームを作り、textctrl.xrc ファイルを吐き出させます。
wxTextCtrl は style に wxTE_PROCESS_ENTER、wxTE_RICH が指定されています。
複数行のwxTextCtrlは改行コードで改行しますが、1行のwxTextCtrlでEnterを入力すると次の入力ツールへ移動してしまいます。wxTE_PROCESS_ENTERを指定することで次の入力ツールへ移動しないようになります。これでエンターキーが入力されたタイミングで関数を実行するようにすることができます。。

wxTE_RICH を指定しないと移動したときは背景色が変化するのですが、フォーカスがオフになっても背景色がもとに戻りません。

  • textctrl.xrc
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
    <object class="wxFrame" name="TextCtrl">
        <style>wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL</style>
        <size>500,300</size>
        <title>TextCtrl</title>
        <centered>1</centered>
        <aui_managed>0</aui_managed>
        <object class="wxPanel" name="m_panel1">
            <style>wxTAB_TRAVERSAL</style>
            <object class="wxBoxSizer">
                <orient>wxVERTICAL</orient>
                <object class="sizeritem">
                    <option>0</option>
                    <flag>wxALL|wxEXPAND</flag>
                    <border>5</border>
                    <object class="wxTextCtrl" name="display">
                        <style>wxTE_PROCESS_ENTER|wxTE_RICH</style>
                        <value></value>
                        <maxlength>0</maxlength>
                    </object>
                </object>
                <object class="sizeritem">
                    <option>0</option>
                    <flag>wxALL|wxEXPAND</flag>
                    <border>5</border>
                    <object class="wxTextCtrl" name="display1">
                        <style>wxTE_RICH</style>
                        <value></value>
                        <maxlength>0</maxlength>
                    </object>
                </object>
                <object class="sizeritem">
                    <option>1</option>
                    <flag>wxALL|wxEXPAND</flag>
                    <border>5</border>
                    <object class="wxTextCtrl" name="display2">
                        <style>wxTE_MULTILINE|wxTE_RICH</style>
                        <value></value>
                        <maxlength>0</maxlength>
                    </object>
                </object>
            </object>
        </object>
    </object>
</resource>

※TextCtrlのスタイルはTE_RICHでなければなりません。(20131226:追記)

module Main where

import Graphics.UI.WX
import Graphics.UI.WXCore

main :: IO ()
main = start gui

gui :: IO ()
gui = do
    res          <- xmlResourceCreateFromFile "textctrl.xrc" wxXRC_USE_LOCALE
    form         <- xmlResourceLoadFrame res objectNull "TextCtrl"
    display      <- xmlResourceGetTextCtrl form "display"
    display1     <- xmlResourceGetTextCtrl form "display1"
    display2     <- xmlResourceGetTextCtrl form "display2"

    -- フォーカスがオン・オフになったときに処理する関数を設定。
    display  `set` [on focus  := onFocus display]
    display1 `set` [on focus  := onFocus display1]
    display2 `set` [on focus  := onFocus display2]

    display  `set` [on endKey      := infoDialog form "display" "pushed EndKey"]
    display1 `set` [on doubleClick := (\_-> infoDialog form "display1" "doubleClicked")]


    -- 閉じるときに確認。
    form     `set` [on closing := confirmExit form]

    focusOn display
    _ <- windowShow form
    return()

onFocus :: Window a -> Bool -> IO ()
onFocus tCtrl True  = windowSetBackgroundColour tCtrl onColor  >>= \_ -> return ()
    where onColor :: Color
          onColor  = rgb (0xbf::Int) (0xcd::Int) (0xdb::Int)

onFocus tCtrl False = windowSetBackgroundColour tCtrl offColor >>= \_ -> return ()
    where offColor :: Color
          offColor = rgb (0xff::Int) (0xff::Int) (0xff::Int)

confirmExit :: Frame () -> IO ()
confirmExit form = do
    yes <- confirmDialog form "終了確認" "終了しますか?" True
    when yes wxcAppExit
    return ()
$ ghc -Wall -package wx Main.hs -o onfocus.exe
[1 of 1] Compiling Main             ( Main.hs, Main.o )
Linking onfocus.exe ...