2008年1月3日木曜日

IEコンポのジャンプ先URLを取得する

HHXソースコード解析によるスクリプト。
リンクをクリックしたときにそのジャンプ先URLを取得します。HHXではこのURLを解析して様々な処理を行っています。

広告による読み込み(Javascript)に対しても反応してしまうようです。
// 他のファイルにジャンプする時いちいち確認するブラウザのサンプル
// 主にhhx.hspから引用
#include "user32.as"
// ie event
#define DIID_DWebBrowserEvents2     "{34A715A0-6587-11D0-924A-0020AFC7AC4D}"
// exdispid.h
#define DISPID_BEFORENAVIGATE2      250   // hyperlink clicked on

#packopt hide 1
    // ウィンドウ最大化を可能にする
    // 参考 -> http://lhsp.s206.xrea.com/hsp_window.html
    screen 0ginfo_dispxginfo_dispyscreen_hide
    GetWindowLong hwnd, -16
    SetWindowLong hwnd, -16stat | $10000 | $40000

    // ActiveXコントロール(IEコンポーネント)の配置
    axobj ieBrowser, "Shell.Explorer.2"
    idIE = stat
    if idIE == -1 {
        dialog "ActiveXコントロールの配置に失敗しました。"1
        end
    }

    ieBrowser->"Navigate" "http://www.yahoo.co.jp/"

    // 割り込み設定
    comevent ieEvent, ieBrowser, DIID_DWebBrowserEvents2*event_ie
    oncmd gosub *event_resize0x0005
    onexit goto *exit

    width 640480
    gsel 01
    stop

// COMイベント発生時のジャンプ先
*event_ie
    if comevdisp(ieEvent) == DISPID_BEFORENAVIGATE2 {
        // URLを取得
        comevarg newurl, ieEvent, 11
        dialog newurl + "\nを開こうとしています。開きますか?"2
        if stat == 7 {
            // 「いいえ」の場合はNAVIGATEをキャンセル
            comevarg Cancel, ieEvent, 62
            Cancel("val") = 1
            delcom Cancel
        }
    }
    return

// ウィンドウのリサイズ
*event_resize
    MoveWindow objinfo(idIE, 2), 00ginfo_winxginfo_winy1
    return

// プログラムの終了処理
*exit
    oncmd 0 : onexit 0
    delcom ieEvent
    delcom ieBrowser
    end

2008年1月2日水曜日

RPG風メッセージウィンドウの描画

ツクールなどでよくありそうなデザインのウィンドウを描画します。三角関数とhsvcolorを組み合わせることで、きれいなグラデーションが表現できます。
白と黒の線で囲むことで、どんな背景でもある程度の見易さを確保するよう努めています。
#module
#include "hspmath.as"
#deffunc line_box int x, int y, int _w, int _h, local w, local h
    w = _w - 1 : h = _h - 1
    line x+w, y, x, y : line x+w, y+h
    line x, y+h : line x, y
    return
#deffunc draw_win int x, int y, int _w, int _h, local w, local h
    w = _w - 1 : h = _h - 1
    repeat 10
        angle = M_PI * cnt/20M_PI * (1+cnt)/20
        hsvcolor 130255255-2*cnt*cnt
        boxf x+sin(angle)*w, y, x+sin(angle(1))*w, y+h
    loop
    color : line_box x, y, _w, _h
    color 255255255 : line_box x+1, y+1, _w-2, _h-2
    return
#global
    redraw 0
    draw_win 00240200
    redraw 1
    stop

lstrlenAとstrlenの速度比較

今回の条件ではlstrlenAよりもstrlenの方が高速な模様。

※別の書き方ではlstrlenAの方が速くなります。むしろそちらの書き方の方が普通と考えられます。m(_ _;)m
// lstrlenAとstrlenの速度比較

#uselib "kernel32.dll"
#cfunc lstrlenA "lstrlenA" sptr

#uselib "winmm.dll"
#cfunc timeGetTime "timeGetTime"

#const trial_times 1000

    font msgothic14
    repeat 31
        trial_strlen = cnt * cnt * cnt * 1000
        sdim trial_string, trial_strlen + 1
        memset trial_string, 'a', trial_strlen

        // lstrlenAの速度計測
        time(0) = timeGetTime()
        repeat trial_times
            tmp = strlen(trial_string)
        loop
        time(0) = timeGetTime() - time(0)

        // strlenの速度計測
        time(1) = timeGetTime()
        repeat trial_times
            tmp = lstrlenA(trial_string)
        loop
        time(1) = timeGetTime() - time(1)

        mes strf("文字列長(%dbytes)の場合:", trial_strlen)
        mes strf(" strlen  :%d[msec]", time(0))
        mes strf(" lstrlenA:%d[msec]", time(1))
        mes ""
    loop
    stop

2007年12月28日金曜日

レジストリを読み出す(advapi32)

advapi32を利用したレジストリ読み出し。HSP3標準エディタの「起動時のカレントディレクトリ」を読み出します。

事前にデータの大きさを知ることができる分、hspextよりも便利かもしれません。
ここでは利用していませんが、エラーの原因を詳しく追及することもできます。// 参考(というか丸写し)
//   ちょくとのページ:レジストリに保存してみる
//   http://yokohama.cool.ne.jp/chokuto/urawaza/registry.html

#uselib "advapi32.dll"
#func global RegCloseKey "RegCloseKey" sptr
#func global RegOpenKeyExA "RegOpenKeyExA" sptr,sptr,sptr,sptr,sptr
#func global RegQueryValueExA "RegQueryValueExA" sptr,sptr,sptr,sptr,sptr,sptr

#const  HKEY_CURRENT_USER   0x80000001
#const  KEY_QUERY_VALUE     0x0001

    // レジストリキーをオープン
    name = "Software\\OnionSoftware\\hsed3"
    RegOpenKeyExA HKEY_CURRENT_USER, name, 0KEY_QUERY_VALUEvarptr(hkey)
    if stat != 0 {
        dialog "キーをオープンできません。"1
        end
    }

    // データのサイズを取得
    RegQueryValueExA hkey, "startdir"000varptr(size) 
    if stat != 0 {
        mes "データサイズを取得できませんでした。"
    } else {
        mes strf("データサイズは%dバイトです。", size)

        // 文字列データを取得
        sdim result, size
        RegQueryValueExA hkey, "startdir"00varptr(result), varptr(size) 
        if stat != 0 {
            mes "データを取得できませんでした。"
        } else {
            mes result
        }
    }

    // レジストリキーのハンドルをクローズ
    RegCloseKey hkey
    stop

レジストリを読み出す(hspext)

レジストリを読み出すスクリプト。
HSP3標準エディタの「起動時のカレントディレクトリ」を読み出します。#include "hspext.as"
#const HKEY_CURRENT_USER 0

    // HSP3標準スクリプトエディタの設定を指定する
    regkey HKEY_CURRENT_USER"Software\\OnionSoftware\\hsed3"0
    if stat != 0 {
        dialog "何らかのエラーが発生しました。"1
        end
    }

    // 起動時のカレントディレクトリを取得
    sdim result, 256
    getreg result, "startdir"1256
    if stat != 0 {
        dialog "何らかのエラーが発生しました。"1
        end
    }

    // 結果を表示
    mes result

    stop

2007年12月26日水曜日

文字列の分割と結合

ActionScript3(AS3)にあるメソッド、split(文字列の分割)とjoin(文字型配列変数の結合)をHSP標準の文字列操作命令で実装。
splitの方は正規表現で何とかできそうな気がしますが……VBScriptのRegExpにはsplitメソッドが備わっていないようなので、少し難しいのでしょうか。ただいま調査中です。

区切り文字の数が多く、さらに区切り文字で終わる文字列をsplitできなかった不具合を修正。
#module
// 文字列の分割
#deffunc split array arr, str target, str devider
    if devider = "" {
        // 分割する目印は空文字であってはならない
        return 1
    }

    dim part_strlen, 10             // 分割結果の長さ
    part_strlen_max = 0             // 分割結果の長さの最大値
    parts_num = 1                   // 分割結果の数
    _target = target                // instr,strmidを使うために変数に代入する
    target_strlen = strlen(target)  // 分割する文字列の長さ
    devider_strlen = strlen(devider)// 分割する目印の長さ

    // いくつに分割できるか調べる
    repeat
        ins = instr(_target, cnt, devider)
        if ins == -1 {
            part_strlen(parts_num - 1) = target_strlen - cnt
            if part_strlen_max < part_strlen(parts_num - 1) {
                part_strlen_max = part_strlen(parts_num - 1)
            }
            break
        } else {
            part_strlen(parts_num - 1) = ins
            if part_strlen_max < ins {
                part_strlen_max = ins
            }
            parts_num++
            continue cnt + ins + devider_strlen
        }
    loop

    // 分割結果代入用の配列を確保
    sdim arr, part_strlen_max + 1, parts_num

    // 分割の開始
    position = 0
    foreach arr
        arr(cnt) = strmid(_target, position, part_strlen(cnt))
        position += part_strlen(cnt) + devider_strlen
    loop
    return 0

// 文字列の結合
#deffunc join var result, array target, str connecter
    if vartype(target) != 2 {
        // 結合する配列変数は文字列型でなければならない
        return 1
    }

    connecter_strlen = strlen(connecter)
    // 連結結果の長さを調べる
    result_strlen = connecter_strlen * (length(target) - 1)
    repeat length(target)
        target_strlen(cnt) = strlen(target(cnt))
        result_length += target_strlen(cnt)
    loop

    // 連結結果代入用の変数を確保
    sdim result, result_length + 1

    // 連結の開始
    position = 0
    foreach target
        if cnt {
            poke result, position, connecter
            position += connecter_strlen
        }
        poke result, position, target(cnt)
        position += target_strlen(cnt)
    loop
    return 0

// ちょっと遠回りな置換
#deffunc replace var target, str before, str after
    split tmparr, target, before
    if stat : return stat
    join target, tmparr, after
    return stat
#global

// サンプルスクリプト
    font msgothic14
    s = "Hot Soup Processor"
    mes s

    mes "\n半角スペースで分割"
    split arr, s, " "
    foreach arr
        mes "{"+cnt+"}:"+arr(cnt)
    loop

    mes "\nエクスクラメーションマークで結合"
    join result, arr, "!"
    mes result

    mes "\nsplitとjoinを組み合わせで置換"
    replace s, " ""!"
    mes s
    stop

2007年12月25日火曜日

正規表現を利用したURL&メールアドレスのタグ付け

テキストに含まれるURLやメールアドレスにリンクタグ(aタグ)をつけます。
当初は1バイトずつ切りだして判定する方法を利用していたのですが、分かりづらい上に作りにくかったので正規表現を利用したものに切り替えました。ロジックを書かなくて済む分、かなりシンプルなスクリプトになっています。独自のWikiやBBSなどに利用できるかもしれません。
// 正規表現を利用したURL&メルアドのタグ付け
#module
// 置換処理のメイン部分
#deffunc do_cnv str before, var after, str pattern, str replace
    newcom regexp, "VBScript.RegExp"
    comres after
    regexp("Pattern") = pattern
    regexp("Global") = 1
    regexp -> "Replace" before, replace
    delcom regexp
    return

// URLのタグ付け
#defcfunc add_link str before
    do_cnv before, after, "(http://[-/.~_#0-9a-zA-Z]+)""<a href=\"$1\">$1</a>"
    return after

// メールアドレスのタグ付け
#defcfunc add_mailto str before
    do_cnv before, after, "([-/.~_0-9a-zA-Z]+@[-.~_0-9a-zA-Z]+)""<a href=\"mailto:$1\">$1</a>"
    return after
#global

// URLにリンク(日本語ドメイン非対応)
    before = {"文字列中のURL(URI)にリンクします
HSPTV!(http://hsp.tv/)
HSP開発wiki(http://hspdev-wiki.net/)
http://だけではリンクされません"}

    after1 = add_link(before)
    mesbox after1, ginfo_winxginfo_winy / 2

// メールアドレスにリンク
    before = {"文字列中のメールアドレスにリンクします
例えばsample2007@yaboo.co.jpとか!"}

    after2 = add_mailto(before)
    mesbox after2, ginfo_winxginfo_winy / 2
    stop