ラベル COM の投稿を表示しています。 すべての投稿を表示
ラベル COM の投稿を表示しています。 すべての投稿を表示

2008年3月1日土曜日

日数計算・曜日計算

COMを利用した、日付を扱うモジュールです。

指定した日の曜日を算出する関数と、指定した2つの日の差(日数)を算出する関数を含んでいます。
日数算出は「あと何日あるか」を算出するので、このサンプルプログラムのように「全部で何日か」を計算する場合は1を足す必要があります。

/*
    日付を扱うライブラリになりそうなもの。
    ※ 注意!パラメータチェック&エラーチェック処理未実装!

    参考:http://tsu.sakura.ne.jp/article/note/eid512.html
*/


#module
// ミリ秒を日に変換
#define ctype cnvMsec2Day(%1int((%1)/86400000)  // 86400000 = 1000*60*60*24
// javascript数式の計算
#defcfunc jsEval str jsExp
    if vartype(mssc) != vartype("comobj") {
        newcom mssc, "MSScriptControl.ScriptControl"
        comres result
        mssc("Language") = "JScript"
    }
    mssc -> "Eval" jsExp
    return result
// 曜日を返す(0~6)
#defcfunc getDayOf int y, int m, int d
    return int(jsEval("(new Date(" + y + "," + (m - 1) + "," + d + ")).getDay();"))
// 時間差を日数で返す
#defcfunc getSub int y1, int m1, int d1, int y2, int m2, int d2
    return cnvMsec2Day(jsEval("Date.UTC(" + y2 + "," + (m2 - 1) + "," + d2 + ") - Date.UTC(" + y1 + "," + (m1 - 1) + "," + d1 + ");"))
#global

// モジュールここまで
    day = "日""月""火""水""木""金""土"
    mes "今年は" + (1 + getSubgettime(0), 11gettime(0), 1231 )) + "日間です"
    mes "今日は" + day( getDayOfgettime(0), gettime(1), gettime(3) ) ) + "曜日です"
    stop

2008年1月28日月曜日

サイトのサムネイルを表示する

サイトのサムネイルを作成・表示するAPI「ThumbnailAPI」を利用します。
ネットの接続などはスクリプトから明示的には行っていません。imgload命令の内部で使用しているCOMが自動で行ってくれているようです。
#include "mod_img.as"
    imgload "http://img.simpleapi.net/small/http://www.forest.impress.co.jp/"
    stop

2008年1月24日木曜日

複数行文字列の行数を取得する(2)

FUJIさんのご指摘を受けて、HSP標準のnotemaxとほぼ同等の動作をするモジュール。

参考:複数行文字列の行数を取得する

// 行数取得モジュール
// 変数の型チェックは行っていないので注意
#module
// instr()を利用した行数の取得
#defcfunc get_lines_num1 var p1
    result = 0
    repeat strlen(p1)
        result++
        ins = instr(p1, cnt"\n")
        if ins == -1 : break
        continue cnt + ins + 2
    loop
    return result
// 正規表現を利用した行数の取得
#defcfunc get_lines_num2 var p1
    if vartype(com_regexp) != vartype("comobj") {
        // comオブジェクト型変数の初期化
        newcom com_regexp, "VBScript.RegExp"
        comres com_result
        com_regexp("Pattern") = "\\r\\n"
        com_regexp("Global") = 1
    }
    com_regexp->"Execute" p1
    result = com_result("Count") + 1    // 行数 = 改行の個数 + 1
    s = strmid(p1, -12)
    if s == "\n" | s == "" : result--   // 最後が空行ならその行をカウントしない
    return result
// notemaxを利用した行数の取得
#defcfunc get_lines_num3 var p1
    notesel p1
    result = notemax
    noteunsel
    return result
#global
    sdim s, 323
    s(0) = "Hot\nSoup\nProcessor"
    s(1) = "sample\nstrings\n"
    s(2) = ""
    foreach s
        mes get_lines_num1(s(cnt))
        mes get_lines_num2(s(cnt))
        mes get_lines_num3(s(cnt))
        mes "***"
    loop
    stop

2008年1月23日水曜日

複数行文字列の行数を取得する

notemaxのように複数行文字列の行数を取得します。
正規表現版はパターンを"(\\r\\n)+"に変更することで、空行を無視するようにもできます。
#module
// instr()を利用した行数の取得
#defcfunc get_lines_num var p1
    result = 0
    repeat
        result++
        ins = instr(p1, cnt"\n")
        if ins == -1 : break
        continue cnt + ins + 2
    loop
    return result
// 正規表現を利用した行数の取得
#defcfunc get_lines_num2 var p1
    if vartype(com_regexp) != vartype("comobj") {
        // comオブジェクト型変数の初期化
        newcom com_regexp, "VBScript.RegExp"
        comres com_result
        com_regexp("Pattern") = "\\r\\n"
        com_regexp("Global") = 1
    }
    com_regexp->"Execute" p1
    return com_result("Count") + 1      // 行数 = 改行の個数 + 1
#global

    s = "Hot\nSoup\nProcessor\n\n"
    mes get_lines_num(s)
    mes get_lines_num2(s)
    stop

2008年1月13日日曜日

数式の分解

正規表現を使って数式を分解し、文字列型配列変数に代入します。
日本語が使えないのが難点です。


関連:インタプリンタ電卓もどき
#runtime "hsp3cl"
#module
// 正規表現を利用した数式の分解
// 英数字およびアンダースコア・半角丸かっこと各種演算子のみ使用可能(日本語は無視)
#deffunc split_calc array result, str exp
    newcom oReg, "VBScript.RegExp"
    comres oMatches
    oReg("Global") = 1

    oReg("Pattern") = "[0-9\\.]+|\\+|-|\\*|/|%|=|\\w*\\(|\\)|\\w+"
    oReg -> "Execute" exp

    sdim result, 16, oMatches("Count")
    bracket_l = 0 : bracket_r = 0
    repeat oMatches("Count")
        oMatch = oMatches("Item"cnt)
        result(cnt) = oMatch("Value")
        s = strmid(result(cnt), -11)
        if s == "(" : bracket_l++ : else : if s == ")" : bracket_r++
    loop
    return bracket_l != bracket_r
#global

    exp = "s(r) = r * r * 3.14"
    mes exp + "\n"

    // 数式を分解
    split_calc result, exp
    if stat : mes "括弧の数が不正です。"

    // 結果の表示
    foreach result
        mes result(cnt)
    loop
    stop

2008年1月7日月曜日

APIを利用して英語を日本語に翻訳するモジュール

英語を日本語に翻訳します。
ネットに接続するため、少し時間がかかります。
// 英語->日本語変換サンプル
// 翻訳APIを使用
//     http://muumoo.jp/news/2007/05/09/0translationapi.html
// 参考:mod_rss.as

#module mod_translate
#deffunc rss2load_init@mod_translate
    newcom oDom,"Microsoft.XMLDOM"
    oDom("async") = "FALSE"
    comres elm_desc
    return

#deffunc rss2load@mod_translate array desc, str url, int p_max
    oDom->"load" url
    oRoot = oDom("documentElement")
    if varuse(oRoot) == 0 : return 1
    if oRoot("tagName") != "rss" : return 2

    maxnum = p_max
    if maxnum <= 0 : maxnum = 5

    oDom->"getElementsByTagName" "description"
    max = limit(elm_desc("length"), 1, maxnum)

    sdim desc, 64, max
    repeat max
        node = elm_desc("item"cnt)
        node2 = node("firstChild")
        desc(cnt) = node2("nodeValue")
    loop

    return 0

#deffunc rss2load_clean onexit
    if vartype(oRoot) == vartype("comobj") {
        delcom node : delcom node2 : delcom oRoot
    }
    delcom elm_desc : delcom oDom
    return

// 英文を和訳します。変換に成功するとstatに0が代入され、第1引数の変数に変換結果が代入されます。
// 変換に失敗するとstatに1が代入されます。
#deffunc eng2jp var result, str before, local after
    rss2load after, "http://pipes.yahoo.com/poolmmjp/ej_translation_api?_render=rss&text=" + before
    if (stat == 0)&(length(after) == 2) {
        // after(0)にはAPIの説明が代入されている
        result = after(1)
        return 0
    } else {
        return 1
    }
#global
    rss2load_init@mod_translate
// モジュールここまで

    target = "Good morning! How are you today?""I'm fine, thank you. And you?""So so."
    foreach target
        mes target(cnt)
        eng2jp result, target(cnt)
        if stat == 0 : mes "-> " + result
    loop
    stop

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

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

2007年11月29日木曜日

Excelによる円グラフの描画

先ほどアップしたスクリプトは円グラフのサンプルとしては分かりづらかったので、よりシンプルなものを作成しました。

なお棒グラフの描画はHSP-NEXTさんにサンプルがあります。
// 参考
// ・日経ソフトウェア 2008年1月号
// ・HSP-NEXT HSPサンプル蔵(COMオブジェクト編)
//      http://hspnext.com/hspkura/hspkura11.htm

    newcom xlApp, "Excel.Application"
    xlApp("Visible") = 1            // ウィンドウを表示
    xlApp("DisplayAlerts") = 0      // 警告メッセージを表示させない
    xlBooks = xlApp("Workbooks")    // Workbooks コレクション取得
    xlBook = xlBooks("Add")         // ワークブックを追加
    xlSheet = xlBook("Worksheets""sheet1")    // シート取得

    // データの書き込み
    repeat 5
        xlRange = xlSheet("Range""A" + (cnt + 1))     // 代入先セルの指定
        xlRange("Value") = rnd(70) + 30                 // 値の代入
    loop

    // グラフの作成
    xlCharts = xlApp("Charts")
    xlChart = xlCharts("Add")
    xlChart("ChartType") = 5                // 円グラフ(xlPie = 5)
    xlRange = xlSheet("Range""A1:A5")     // データの範囲
    xlChart -> "SetSourceData" xlRange, 2   // グラフの元データを指定
    xlChart -> "Location" 2"sheet1"       // グラフの位置(既存のシートに貼り付け)

    // COMオブジェクト型変数の破棄
    delcom xlRange  : delcom xlChart
    delcom xlCharts : delcom xlSheet
    delcom xlBook   : delcom xlBooks
    delcom xlApp

    stop

拡張子ごとの合計ファイルサイズを求める

任意のフォルダ内にあるファイルのサイズを取得し、拡張子ごとに分類・合計して出力します。
最もサイズの大きいファイルが調べられて、少し楽しいかも知れません。私の場合は素材として保存してあるBMPファイルが最大でした。HSPスクリプトは60MB、ちょっと少ないかも知れません。

// 参考
// ・日経ソフトウェア 2008年1月号
// ・HSP開発wiki COMDictionary
//      http://hspwiki.tm.land.to/?COMDictionary
// ・HSP-NEXT HSPサンプル蔵(COMオブジェクト編)
//      http://hspnext.com/hspkura/hspkura11.htm

#include "hspext.as"
    // Dictionaryの準備
    newcom dc, "Scripting.Dictionary"
    comres comret
    dc("compareMode") = 1   // 大文字・小文字を同一視

    sdim exts, 810        // 拡張子名を代入する配列変数
    ext_num = 0             // 拡張子の種類数

    // 処理開始
    gosub *select_folder    // 検索対象フォルダの指定
    gosub *get_data         // ファイルを検索しデータを作成
    gosub *make_graph       // Excelによるグラフの作成

    // Dicitonaryの破棄
    delcom dc
    end

*select_folder
    target_folder = ""
    selfolder target_folder, ""
    if stat == 1 {
        dialog "フォルダの選択がキャンセルされました。"
        end
    }
    return

*get_data
    mes "データを取得しています..."
    notesel file_list
    sdim file_list, 1024
    sdim folder_names, 25610
    sdim file_name, 256
    sdim folder_name, 256
    folder_names(0) = target_folder
    folder_num = 0

    // 選択したフォルダの中にあるファイルをすべて検索
    // 再帰を利用しない方法
    repeat
        chdir folder_names(folder_num)
        // ファイル一覧を取得
        dirlist file_list, "*"1
        repeat stat
            noteget file_name, cnt
            exist file_name
            if strsize > 0 {
                file_size = strsize
                ext = getpath(file_name, 2// 拡張子を取り出す
                dc -> "Exists" ext

                if comret {
                    // すでにデータが存在している場合
                    file_size += dc("Item", ext)
                    dc -> "Remove" ext      // Itemプロパティに対する上書きがうまくいかないので、いったん消去
                } else {
                    // まだデータが存在していない場合
                    exts(ext_num) = ext
                    ext_num++
                }
                dc -> "Add" ext, file_size
            }
        loop

        // フォルダー一覧を取得
        dirlist file_list, "*"5
        folder_num--
        repeat stat
            // カレントフォルダにあるフォルダの名前を
            // ひとつずつfolder_namesへ代入
            folder_num++
            noteget folder_name, cnt
            folder_names(folder_num) = dir_cur + "\\" + folder_name
        loop
        if folder_num < 0 : break
        await 1
    loop
    mes "データ取得が終了しました。"
    return

*make_graph
    mes "グラフを作成しています..."
    newcom xlApp, "Excel.Application"
    xlApp("Visible") = 1            // ウィンドウを表示
    xlApp("DisplayAlerts") = 0      // 警告メッセージを表示させない
    xlBooks = xlApp("Workbooks")    // Workbooks コレクション取得
    xlBook = xlBooks("Add")         // ワークブックを追加
    xlSheet = xlBook("Worksheets""sheet1")    // シート取得

    // データの書き込み(拡張子ごとのデータ)
    repeat ext_num
        xlRange = xlSheet("Range""A" + (cnt + 1))         // 代入先セルの指定
        xlRange("Value") = exts(cnt)                        // 値の代入
        xlRange = xlSheet("Range""B" + (cnt + 1))         // 代入先セルの指定
        xlRange("Value") = dc("Item", exts(cnt))            // 値の代入
    loop
    // データの書き込み(合計値の算出)
    xlRange = xlSheet("Range""A" + (ext_num + 1))     // 代入先セルの指定
    xlRange("Value") = "合計"                           // 値の代入
    xlRange = xlSheet("Range""B" + (ext_num + 1))     // 代入先セルの指定
    xlRange("Value") = "=SUM(A1:B" + ext_num + ")"      // 値の代入

    // グラフの作成
    xlCharts = xlApp("Charts")
    xlChart = xlCharts("Add")
    xlChart("ChartType") = 5                        // 円グラフ
    xlRange = xlSheet("Range""A1:B" + ext_num)    // データの範囲
    xlChart -> "SetSourceData" xlRange, 2           // グラフの元データを指定
    xlChart -> "Location" 2"sheet1"               // グラフの位置(既存のシートに貼り付け)

    // COMオブジェクト型変数の破棄
    delcom xlRange  : delcom xlChart
    delcom xlCharts : delcom xlSheet
    delcom xlBook   : delcom xlBooks
    delcom xlApp

    mes "グラフを作成しました。"
    return

2007年11月27日火曜日

IEコンポーネントによるRSSリーダー

本家BBSにて、動的にHTMLを記述するスクリプトを見て作成。
IEはあまり好きではないのですが(普段はFxを使用)、ほぼすべての環境で動作する点が長所ですね。
hspailさんのスクリプトをほぼそのまま流用しています(感謝!)が、とても基本的なスクリプトなので著作権は発生しないと考え、無許可で載せています。

ついでにmod_rss.asを利用してみました。mod_rss.as内部ではCOMを利用しています。
#include "mod_rss.as"
//  RSSリーダーサンプル
//  付属サンプル(rssload.hsp)を改造
//  また、HSPTV!のBBSよりhspailさんのスクリプトを参考とさせていただきました。
    title "Loading..."

    url="http://hspwiki.tm.land.to/?cmd=rss&ver=1.0"
    rssload desc, link, url, 15

    if stat == 1 : dialog "取得に失敗しました。" : end
    if stat == 2 : dialog "RSSではありません。" : end

    axobj ie, "Shell.Explorer.2"ginfo_winxginfo_winy
    if stat == -1 {
        dialog "ActiveXコントロールの配置に失敗しました。"1
        end
    }

    title url
    code = {"<html><body>
\t<p>クリックすると別ウィンドウでリンク先を開きます。</p>
\t<ol>\n"}


    foreach desc
        code += "\t<li><a href=\"" + link(cnt) + "\" target=\"_blank\">" + desc(cnt) + "</a></li>\n"
    loop
    code += "\t</ol>\n</body></html>"

    ie -> "Navigate" "about:blank"
    doc = ie("Document")

    doc -> "write" code
    stop

2007年9月21日金曜日

動的SQLによる数独の超高速解法(by CodeZine)

SQLele利用スクリプト第4弾。
みんな大好きCodeZine様より転載しました。元記事は動的SQLによる数独の超高速解法。よって今回の記事を利用する場合はCodeZine様の規約に従ってください。
元記事の章・節に合わせたコメントが付いています。

……しかしこれはすごいですね。
SQLで数独を解くという発想もさることながら、その速度が充分実用的な点に驚かされます。
解法が複数ある場合でもすべて示してくれるのも素晴らしいです。

WHERE節の条件重複を回避するためにxnoteaddを利用しようとしたのですが、原因不明のエラーで落ちてしまうので独自命令で対応しています。生成されるSQL文を元記事と全く同じにするためにはWHERE節のソートも必要だったのですが、sortnoteの仕様(空行追加)がややこしかったので考慮していません。
// http://codezine.jp/a/article/aid/1629.aspx
// 動的SQLによる数独の超高速解法
#runtime "hsp3cl" 
#include "sqlele.hsp"
#module
// 文字列の置換(参考:サンプルスクリプトcompbj/comtest9.hsp)
#deffunc replace var target, str before, str after
    newcom o_reg, "VBScript.RegExp"
    comres target
    o_reg( "Pattern" ) = before         // 検索パターンの設定
    o_reg( "Global" ) = 1               // すべて置換する
    o_reg -> "Replace" target, after    // 検索の実行
    delcom o_reg
    return
// xnoteadd代替命令(今回は問題ないが、完全互換ではない点に注意)
#deffunc xnoteadd_ var target, str add
    if instr( target, 0, add + "\n" ) < 0 {
        target += add + "\n"
    }
    return
#global
    dim problem, 99
    problem(00) = 1,0,0,0,0,7,0,9,0
    problem(01) = 0,3,0,0,2,0,0,0,8
    problem(02) = 0,0,9,6,0,0,5,0,0
    problem(03) = 0,0,5,3,0,0,9,0,0
    problem(04) = 0,1,0,0,8,0,0,0,2
    problem(05) = 6,0,0,0,0,4,0,0,0
    problem(06) = 3,0,0,0,0,0,0,1,0
    problem(07) = 0,4,0,0,0,0,0,0,7
    problem(08) = 0,0,7,0,0,0,3,0,0
    max_num = length( problem )
    m = intsqrtlength( problem ) ) )

    sdim select_items, 6400
    sdim from_items, 6400
    sdim where_items, 30000

    // SELECT文の生成
    for row1, 0, max_num
        for col1, 0, max_num
            label1 = "R" + ( row1 + 1 ) + "C" + ( col1 + 1 )
            // SELECT節
            if problem( col1, row1 ) != 0 {
                item1 = str( problem( col1, row1 ) )
            } else {
                item1 = "t" + label1 + ".n"
            }
            select_items += item1 + " AS " + label1 + ","
            // FROM節
            if problem( col1, row1 ) == 0 {
                from_items += "nums t" + label1 + ","
            }
            // WHERE節
            for row2, 0, max_num
                for col2, 0, max_num
                    if ( problem( col1, row1 ) == 0 ) | ( problem( col2, row2 ) == 0 ) {
                        if (( row1 == row2 ) & ( col1 != col2 )) | (( row1 != row2 ) & ( col1 == col2 )) | (( row1 != row2 ) & ( col1 != col2 ) & ( row1 / m == row2 / m ) & ( col1 / m == col2 / m )) {
                            label2 = "R" + ( row2 + 1 ) + "C" + ( col2 + 1 )
                            if problem( col2, row2 ) != 0 {
                                item2 = str( problem( col2, row2 ) )
                            } else {
                                item2 = "t" + label2 + ".n"
                            }
                            if ( item1 != item2 ) < 0 {
                                xnoteadd_ where_items, item1 + "!=" + item2
                            } else {
                                xnoteadd_ where_items, item2 + "!=" + item1
                            }
                        }
                    }
                next
            next
        next
    next
    // SELECTの完成
    sdim sql, 30000
    poke select_items, strlen( select_items ) - strlen"," ), 0        // 最後の余計なカンマを削除
    poke from_items, strlen( from_items ) - strlen"," ), 0            // 最後の余計なカンマを削除
    replace where_items, "\\n"" AND "                                 // 改行を削除
    poke where_items, strlen( where_items ) - strlen" AND " ), 0      // 最後の余計なANDを削除
    sql = "SELECT " + select_items + " FROM " + from_items + " WHERE " + where_items
;   notesel sql : notesave "sql.txt"

// クエリの実行
    // テーブル:numsの準備
    sql_open ":memory:"
    sql_q "CREATE TABLE nums (n INTEGER NOT NULL PRIMARY KEY);"
    repeat 91
        sql_q "INSERT INTO nums VALUES (" + prm_i(cnt) + ");"
    loop
    // 結果の取得
    sql_q sql
    repeat stat1
        mes "Solution No." + cnt
        for r, 0, max_num
            s = ""
            for c, 0, max_num
                s += strf("%1d "sql_i"R" + ( r + 1 ) + "C" + ( c + 1 ) ) )
            next
            mes s
        next
        sql_next
    loop

    sql_close
    stop

2007年5月3日木曜日

COMによるショートカットの作成

ヘルプにも載っているCOMによるショートカットの作成。// COMの練習。似非ハンガリアン記法も導入してみた
//    fn = File_Name, dn = Directory_Name
//    id = object_ID, s  = String
//    c  = Com_object
// 参考 ・http://yokohama.cool.ne.jp/chokuto/urawaza/com/shell.html
//      ・http://ameblo.jp/argv/entry-10031517216.html
#include "hspext.as"

// シェルリンクオブジェクトのクラスID
    #define  CLSID_ShellLink   "{00021401-0000-0000-C000-000000000046}"
// IShellLinkインターフェースのインターフェースID
    #define  IID_IShellLinkA   "{000214EE-0000-0000-C000-000000000046}"
// IShellLinkインターフェースの持つSetPathメソッド
    #usecom  IShellLinkA IID_IShellLinkA
    #comfunc IShellLink_SetPath 20 str

// IPersistFileインターフェースのインターフェースID
    #define  IID_IPersistFile  "{0000010b-0000-0000-C000-000000000046}"
// IPersistFile のインターフェースの持つSaveメソッド
    #usecom  IPersistFile IID_IPersistFile
    #comfunc IPersistFile_Save 6 wstr, int

// 変数の初期化
    dnShortcut = DIR_DESKTOP
    fnShortcut = "shortcut.lnk"
    fnTarget   = dir_exe + "\\hsed3.exe"
    sTmp       = ""
    newcom cSLink, CLSID_ShellLink

// 画面の初期化
    gosub *makeScreen

    stop

*makeScreen
    screen 0380200
    objmode 11
    syscolor 5 : boxf
    syscolor 8 : sysfont 17

    pos  30,  30 : mes "対象ファイル"
    pos  30,  70 : mes "保存先フォルダ"
    pos  30110 : mes "ショートカットの名前"

    objsize 160
    pos 130,  27 : input fnTarget   : idInputTargetName    = stat
    pos 130,  67 : input dnShortcut : idInputDirectoryName = stat
    pos 130107 : input fnShortcut : idInputShortcutName  = stat

    objsize 60
    pos 290,  27 : button gosub "選択"*selectTarget
    pos 290,  67 : button gosub "選択"*selectDirectory
    pos 290107 : button gosub "選択"*selectShortcut

    objsize 32040
    pos  30150 : button gosub "ショートカット作成"*makeShortcut
    return

*makeShortcut
    // パスの確認
    exist fnTarget
    if strsize < 0 {
        dialog "対象ファイルのパスが正しくありません。"1
        return
    }

    // 保存先フォルダの存在を確認
    dirlist sTmp, dnShortcut, 5
    if stat == 0 {
        dialog "保存先フォルダのパスが正しくありません。"1
        return
    }

    // 上書き確認
    exist dnShortcut + "\\" + fnShortcut
    if strsize >= 0  {
        dialog "既にファイルが存在します。上書きしますか?"2
        if stat == 7 : return
    }

    // ショートカット作成を実行
    IShellLink_SetPath cSLink, fnTarget
    IPersistFile_Save  cSLink, dnShortcut + "\\" + fnShortcut, 1
    // 上2行は以下とほぼ同値 (hspext)
    ; chdir dnShortcut
    ; fxlink getpath(fnShortcut, 1), fnTarget

    dialog "ショートカットを作成しました。"
    return

*selectDirectory
    selfolder sTmp, ""
    if stat == 0 {
        dnShortcut = sTmp
        objprm idInputDirectoryName, sTmp
    }
    return

*selectTarget
    dialog "*"16
    if stat == 1 {
        fnTarget = refstr
        objprm idInputTargetName, fnTarget
    }
    return

*selectShortcut
    dialog "lnk"17
    if stat == 1 {
        fnShortcut = getpath(refstr1) + ".lnk"
        objprm idInputShortcutName, fnShortcut
    }
    return