リッチエディットコントロールを作成してみる ACT-2

文字書式の部分的な設定

前回作成したリッチエディットは、コントロールに入力される文字すべてが最初に設定した文字書式で統一されていました。今回は、選択された部分の文字書式を自由に変えてみましょう。


前回説明した通り、文字の書式を設定をするには CHARFORMAT 構造体に書式情報を格納し、コントロールに EM_SETCHARFORMAT メッセージを送信します。

このとき、 EM_SETCHARFORMAT メッセージの wParam パラメータに 0x0001 (SCF_SELECTION) を指定すると、現在選択されている領域の文字書式を設定することができます。領域が選択されていない場合でも、現在のカーソル位置に次に入力される文字にはその書式が適用されます。

テキストサイズの上限の設定

通常のWindows標準エディットコントロールでは、初期状態で 32K バイト未満、最大でも64Kバイト未満のテキストしか扱うことができませんでした。

リッチエディットコントロールでは、初期状態こそ標準エディットコントロールと同じ 32K バイトですが、テキストの上限サイズを設定し直すことで、はるかに多くのテキストを扱うことができるようになっているのです。

リッチエディットコントロールを作成した時点では、テキストサイズは 32K バイト未満となっているので EM_EXLIMITTEXT メッセージを送信して、テキストサイズの上限を増やします。

#define  EM_EXLIMITTEXT    0x0435

EM_EXLIMITTEXT
    wParam = 0;
    lParam = cchTextMax;

cchTextMax パラメータには、新しく設定するテキストサイズをバイト単位で指定します。このパラメータに 0 を指定すると、 64K バイト未満のテキストが扱えるように設定されます。

サンプルスクリプト

今回は特に説明することはないので、さっそくスクリプトを書いてみましょう。

HSPウィンドウID2 を文字書式設定用のウィンドウとして使用します。「フォント変更」ボタンが押されたらこのウィンドウを表示して、「OK」ボタンが押されたらこのウィンドウを消して文字書式を実際に反映させます。

サンプルスクリプト main.as

    #include "llmod.as"

    objsize winx, 24 : button "フォント変更", *lb_fontdialog

    ; RICHEDIT.DLLのロード
    ll_libload hRtLib, "RICHED32.DLL"

    ; リッチエディットコントロールの作成
    mref bmscr, 67              ; 描画中ウィンドウのBMSCR構造体
    classname = "RichEdit"
    pm.0 = 0
    getptr pm.1, classname
    pm.2 = 0
    pm.3 = 0x50A00044           ; WS_CHILD | WS_VISIBLE | WS_BORDER
                                ;  | WS_VSCROLL | ES_MULTILINE
                                ;  | ES_AUTOVSCROLL
    pm.4 = 0, 24, winx, winy-24
    pm.8 = bmscr.13             ; 描画中HSPウィンドウのハンドル
    pm.9 = 0xFF00               ; コントロールID (大きめに指定)
    _get_instance pm.10         ; インスタンスハンドル取得
    pm.11 = 0
    dllproc "CreateWindowExA", pm, 12, D_USER
    hEdit = stat                ; リッチエディットのハンドル

    ; テキストサイズの上限の設定
    ; EM_EXLIMITTEXT メッセージ送信
    pm = hEdit, 0x0435, 0
    pm.3 = 10 * 1024 * 1024     ; 10Mバイトに設定
    sendmsg pm

    ; デフォルトの書式
    fontname = "MS ゴシック"  ;フォント名
    fontsize = 16               ; フォントの高さ(ピクセル単位)
    clr = 0, 0, 0               ; 文字色(赤, 緑, 青)
    fbold = 0                   ; 1 のとき太字
    fitalic = 0                 ; 1 のときイタリック体
    fudline = 0                 ; 1 のとき下線付き
    fstkout = 0                 ; 1 のとき取り消し線付き

    ; 書式設定ウィンドウ
    screen 2, 300, 300, 2       ; 非表示で作成

    pos 20, 10 : mes "フォント名"
    input fontname, 180, 24

    pos 20, 60 : mes "フォントサイズ(ピクセル)"
    input fontsize , 50, 24

    pos  20, 110 : mes "フォントの色"
    pos  30, 130 : mes "赤" : input clr.0, 50, 24
    pos 100, 130 : mes "緑" : input clr.1, 50, 24
    pos 170, 130 : mes "青" : input clr.2, 50, 24

    objsize 100
    pos 20, 180
    chkbox "太字", fbold
    chkbox "イタリック", fitalic
    chkbox "下線", fudline
    chkbox "取り消し線", fstkout

    pos 160, 200 : button "OK", *lb_fontchange
    pos 160, 240 : button "キャンセル", *lb_cansel

    goto *lb_fontchange         ; デフォルトの書式を反映させる

*lb_fontdialog
    ; 「フォント変更」ボタンが押されたとき
    gsel 2, 1                   ; 設定ウィンドウ表示
    stop

*lb_fontchange
    ; デフォルト書式の設定 /「OK」ボタンが押されたとき
    gsel 2, -1                  ; 設定ウィンドウ非表示

    fstyle = 0
    if fbold   : fstyle += 1    ; CFE_BOLD
    if fitalic : fstyle += 2    ; CFE_ITALIC
    if fudline : fstyle += 4    ; CFE_UNDERLINE
    if fstkout : fstyle += 8    ; CFE_STRIKEOUT

    ; 文字書式を設定
    ; RichEditのデバイスコンテキスト取得
    pm = hEdit
    dllproc "GetDC", pm, 1, D_USER
    hdcEdit = stat

    ; RichEditのy方向の1インチ当たりのピクセル数を取得
    pm = hdcEdit, 90            ; LOGPIXELSY
    dllproc "GetDeviceCaps", pm, 2, D_GDI
    pxl = stat                  ; 1インチ当たりのピクセル数

    ; デバイスコンテキスト解放
    pm = hEdit, hdcEdit
    dllproc "ReleaseDC", pm, 2, D_USER

    ; CHARFORMAT 構造体
    cfm.0 = 60
    cfm.1 = 0xE800000F          ; CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE
                                ;  | CFM_STRIKEOUT | CFM_CHARSET
                                ;  | CFM_FACE | CFM_SIZE | CFM_COLOR
    cfm.2 = fstyle
    cfm.3 = fontsize*1440/pxl   ; 文字高( pixel → twip に変換)
    cfm.5 = clr.0 | (clr.1<<8) | (clr.2<<16)  ; 文字色(0x00BBGGRR の形に)
    poke cfm, 24, 128           ; SHIFTJIS_CHARSET
    poke cfm, 26, fontname      ; フォント名

    ; EM_SETCHARFORMATメッセージ送信
    pm = hEdit, 0x0444
    pm.2 = 0x0001               ; SCF_SELECTION
    getptr pm.3, cfm            ; CHARFORMAT構造体のアドレス
    sendmsg pm
    if stat == 0 : dialog "書式の設定に失敗しました。", 1, "エラー"
    stop

*lb_cansel
    ;「キャンセル」ボタンが押されたとき
    gsel 2, -1                  ; 設定ウィンドウ非表示
    stop