AX

電霊ログ

私のやってるサイト、電子の言霊の活動ログ

カテゴリークラウド

タグリスト

最近のトラックバック

月別アーカイブ(タブ)

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  • VBScript が実行できない

少し前から VBScript がなぜなのか実行できなくなっていたので、グーグルで調べて解決した備忘録。ちなみにこれが治ったら、スカイプのアップデートのエラーも出なくなった。
!このやり方はレジストリを書き換えます、大事な部分に間違った操作をすると最悪の場合パソコンが起動しなくなるなど危険ですので慎重に完全なる自己責任で行って下さい!


#PC環境はWindows Vista です

HSP で VBScript を呼び出すスクリプトを実行したところ、
newcom objVBsc, "ScriptControl"
objVBsc("Language") = "VBScript"
「#Error 39 in line 2 (C:\***\***)
 -->外部オブジェクトの呼び出しに失敗しました」
というエラーが出て「objVBsc("Language")="VBScript"」の部分で実行できなかった。

そこでWSHの入門サイトを見ながらメモ帳で
Wscript.Echo "メッセージを表示"
という初歩的な内容を「test.vbs」の名前で保存し実行してみたら今度は
「Windows Script Host
 スクリプト "C:\***\***\Desktop\test.vbs" のスクリプト エンジン "VBScript" が見つかりません。」
というエラーが出て実行できない。
これは明らかにおかしいので調べてみることに。


エラーの内容を手がかりに検索して見るとこれらのサイトを見つけた
スクリプト エンジン "VBScript" が見つかりません。
VBScript:VBScriptのファイル(XXX.vbs)を実行すると「"スクリプト エンジン VBScript"が見つかりません」エラーが発生する際の対処方法 - 覚書 - My Knowledge Base - FC2ブログ版
Windows Vistaでvbscript.dllを無効に | Windows系OSのQ&A【OKWave】

いずれもコマンドプロンプトから、
regsvr32 -u vbscript.dll や
regsvr32 vbscript.dll を呼び出すという同じ内容。
この方法で試してみると成功しましたと出るものの解決せず。


さらに調べて見ると別の方法が記されているこのページを見つけた
windows のスプリクトエンジンについて | Windows 7のQ&A【OKWave】

回答No.1の【アンインストールの場合】
の手順通りにやってみたところ、途中レジストリの書き換えの際にエラーが出たもののアクセス許可を与えて解決出来た。これで正常に実行できるようになった。

以下順を追って自分がやった事を書いて見る。
基本的には上記のリンク内の内容とほぼ同じ。


まずレジストリエディタを開く、レジストリエディタを開くには「ファイル名を指定して実行」から「regedt32」と入力してOKを押す。スタートメニューに「ファイル名を指定して実行」が無い事も有るらしいので(ファイル名を指定して実行がない:Windows(ウィンドウズ)の使い方-Windows Vista(ウィンドウズビスタ)
別の方法では、スタートメニューを開いて検索ボックスに「regedit」と入力してファイルを検索し出てきた「regedit.exe」を実行でも出来るはず。

レジストリエディタを開いたら、
「HKEY_CLASSES_ROOT\CLSID\{B54F3741-5B07-11cf-A4B0-00AA004A55E8}\InprocServer32」
この場所を探す。

見つけたら InprocServer32 を選択し、切り替わった右側の画面内にある、(既定)をダブルクリック 又は 右クリックメニューから「修正(M)...」を押して 編集ダイアログを出し、値のデータの記入欄に「C:\Windows\system32\vbscript.dll」と入力してOKを押す。
(自分のところではここが違う値になっていた。だから VBScript が使えなかったんだね)

reg3.png

reg4.png

と、ここまでは上記のリンク先の内容と同一。
しかし自分の場合はここで
「値の編集エラー 〇〇を編集できません。値の内容を書き込み中に、エラーが発生しました。」
というエラーダイアログが出た。
この状況は先のページには書かれていなかったので以下からは自分がやってみた事。

アクセスの許可を設定する。
InprocServer32 の右クリックメニューから「アクセスの許可(P)...」をクリックして「InprocServer32 のアクセス許可」のダイアログを出す。

reg1.png

ダイアログが出たら、「セキュリティ」タブの「グループ名またはユーザー名(G)」内の「Administrators」を選択し、その下の「〇〇 のアクセス許可(P)」欄の中の「フル コントロール」の許可チェックボックスをクリックしオンの状態に(自分は Administrators を変更したけど Users でも良いかも)。

reg2.png

できたらOKを押してダイアログを閉じる。
そしてもう一度(既定)キーの値を変更する。
(最後にアクセス許可の設定を元に戻しといた方が良いかも?)

自分はこれで解決できました まる


更に少し前から Skype のアップデート時に、
「the installer has encountered an unexpected error installing this package. this may indicate a problem with this package. the error code is 2738.」
というエラーが出ていた問題も VBScript を修正したら治っていた。
どうやら Skype が裏で使っていたもよう。
スポンサーサイト
  • [HSP3] 確保した変数を開放する

HSPでは一度確保した変数の領域はプログラムの終了時にまとめて開放されます。プログラムの実行中にメモリを節約するには、
    sdim buf, 256
    buf = "文字列代入"
    sdim buf
などとして使用した変数を再作成する方法があります。

更にモジュール変数を使う事でプログラム実行中に使用している変数のメモリー領域をまとめて開放することが出来ます。実際にメモリー監視ソフトでメモリーの状態を確認しながら実行すると分かりやすいでしょう。

#スクリプトは HSP3.21 で確認

// モジュール変数を利用することで、
// 確保した変数領域を完全に開放する

#module test buf

    #modinit int mega
        sdim buf, 1024 * 1024 * mega
    return

#global

#const SIZE 100

    button "確保"*GET
    button "開放"*FREE
    stop

*GET
    newmod mv, test, size
    n++
    mes strf("%d MB 確保しました(現在の確保数:%d)"SIZE, n)
    stop

*FREE
    if n > 0 {
        n--
        delmod mv.n
        mes strf("%d MB 開放しました(現在の確保数:%d)"SIZE, n)
    }
    stop
変数を普通に作成する代わりに、モジュール変数内で 使用する変数を確保しています。こうする事によって、モジュール変数を delmod すればいつでもモジュール変数内で確保された変数をまとめて解放する事が出来ます。

ただ、モジュール変数の配列の場合 全ての要素を delmod で削除しても、呼び出し元のモジュール変数の 配列の長さまでは変わらないので、配列の長さも短くしたい場合はモジュール変数を作成し直す必要があります。

#module test buf
    #modinit int mega
        sdim buf, 1024 * 1024 * mega
    return
#global
    // モジュール変数を100個作成
    repeat 100
        newmod mv, test, 1
    loop
    // モジュール変数を全て削除
    foreach mv
        delmod mv.cnt
    loop
    // モジュール変数の配列の拡張は100個のまま
    mes "モジュール変数の配列の数:" + length(mv)
    // モジュール変数を再作成
    dimtype mv, vartype("struct")
    // モジュール変数が作り直され配列が1に
    mes "モジュール変数の配列の数:" + length(mv)

この様にモジュール変数を使用する事で 手軽に変数の領域を解放する事が出来るので、マメに開放をしたいという方には良さそうです。

さらに一時期流行ったメモリ解放ソフトなんかも割と楽に作る事が出来るかもしれませんね(現在のPC環境での必要性や、そもそもの効能の是非に付いては置いといて(笑))。

モジュール変数にする事で直接変数にアクセス出来なくなる不便も有るので、何でもかんでもモジュール変数化すれば良いと言う訳では無いと思いますが、モジュール変数を開放する目的のために使うやりかたは 特質や状況を見極めればどこかしら利用する価値は有るかもしれません。
  • [HSP3] Unicodeでファイルを開く

前にHSP本家の掲示板で、ファイル名に中国語を含んだファイルを開く事についての質問があり、Unicode を使えば良いんじゃないかって話のやり取りを見て、自分なりに調べて作ってたスクリプトが有ったんですが、質問者が未解決のまま居なくなってしまって、そのまま投稿する機会を失っていました。せっかく書いたのに公開出来ないのも寂しいので、こちらで公開してみます。(いくらか適当なトコもあったりしますが…)


追記(2014/08/20):
久しぶりにスクリプトを見返したら、あまりにもいい加減すぎたので修正しました。

追記(2015/01/18):
ユニコードを手軽に扱う HSP3 用モジュール mod_unicode をサイトにて公開しました。この記事の内容がよく分からなかったり、自分でやるのが面倒くさい人は使ってみてください。


・指定したテキストファイルのファイル名とその内容の一部をUnicodeとして表示
#スクリプトは HSP3.4rc1 で実行確認しています

#include "comdlg32.as"
#include "user32.as"
#include "kernel32.as"
#include "advapi32.as"

#define MAX_PATH                        $00000104
#define OFN_FILEMUSTEXIST               $00001000
#define OFN_ALLOWMULTISELECT            $00000200
#define OFN_EXPLORER                    $00080000
#define OPENFILENAME_SIZE_VERSION_400   $0000004C
#define DT_WORDBREAK                    $00000010
#define DT_EXPANDTABS                   $00000040
#define GENERIC_READ                    $80000000
#define OPEN_EXISTING                   $00000003
#define FILE_ATTRIBUTE_NORMAL           $00000080
#define INVALID_HANDLE_VALUE            $FFFFFFFF
#define FILE_SHARE_READ                 $00000001
#define CP_ACP                          $00000000
#define MB_PRECOMPOSED                  $00000001


// OPENFILENAME構造体初期化に必要なものを準備

    // フィルター文字列が Unicode で入るだけの大きさを確保
    sdim filter, 512
    // フィルター文字列に置換マーク(0)を埋め込んで Unicode に変換(下で手動で \0 を置換)
    cnvstow filter, "text(*.txt)\0*.txt\0All files(*.*)\0*.*\0\0"           ; HSP に \0 は無いので実際は数字の 0 になる
    // マークを Unicode のヌル文字(2byte の 0x0000)に置換(上書き)
    wpoke filter, 22 :wpoke filter, 34 :wpoke filter, 64 :lpoke filter, 72  ; 終端は並んでるので 4byte 一気に換えてみた
    // ダイアログの選択結果を格納する変数を作成
    sdim filepath, MAX_PATH * 2  ;ここにファイルのパスが入る
    sdim filename, MAX_PATH * 2  ;ここにファイルネームが入る
    cnvstow caption, "開く"

// OPENFILENAME構造体初期化

    // 構造体用の変数を作って適切な値を設定する
#if 01 ; Windows 2000以降ならこっちのサイズを指定するみたい
    dim ofn, 22
    ofn(0) = 88
#else
    dim ofn, OPENFILENAME_SIZE_VERSION_400 / 4
    ofn(0) = OPENFILENAME_SIZE_VERSION_400
#endif
    ofn(1) = hwnd
    ofn(3) = varptr(filter)
    ofn(7) = varptr(filepath), MAX_PATH     ; Unicode 版ではこの MAX_PATH で指定した
    ofn(9) = varptr(filename), MAX_PATH     ; メンバは文字数扱いらしい
    ofn(12) = varptr(caption)
    ofn(13) = OFN_FILEMUSTEXIST

    // ファイルオープンダイアログを表示
    GetOpenFileNameW varptr(ofn)
    if stat = 0 :mes "ダイアログキャンセル" :stop

// 選択したファイルを読み込む

    // 取得したファイルネームを使ってファイルを開きそのハンドルを得る
    CreateFileW varptr(filename), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
    hfile = stat
    if hfile = INVALID_HANDLE_VALUE { mes "CreateFileWでエラー" : stop }

    // テキストファイルの内容を変数に読み込む
    GetFileSizeEx hfile, varptr(filesize)                           ; ファイルのハンドルからファイルサイズ取得
    sdim text, filesize + 2                                         ; ファイルの内容を入れる変数を作成(ヌル文字分加算)
    ReadFile hfile, varptr(text), filesize, varptr(readsize), 0     ; ファイルの内容を取得
    CloseHandle hfile                                               ; ハンドルを閉じる

// 読み込んだファイルを表示

    // ファイルのパスを表示
    font MSGOTHIC16
    mes "ファイルパス:"
    rect = 0GINFO_CY640GINFO_CY + 16 : pos , rect(3)
    DrawTextW hdcvarptr(filepath), -1varptr(rect), DT_WORDBREAK|DT_EXPANDTABS

    // ファイルの名前を表示
    mes "\nファイルネーム:"
    rect = 0GINFO_CY640GINFO_CY + 16 : pos , rect(3)
    DrawTextW hdcvarptr(filename), -1varptr(rect), DT_WORDBREAK|DT_EXPANDTABS

    // ファイルの内容が Unicode か判定し Unicode に合わせる
    IsTextUnicode varptr(text), filesize, 0
    if stat {   /* Unicode ならば */
        // 文字数取得
        lstrlenW varptr(text)       ; ここで取得するのは
        unilen = stat               ; 文字サイズでなく文字数(ヌル文字は含まれない)
        mes "\nファイルの内容 (Unicode) : "
    } else {    /* Shift_JIS ならば */
        // 文字数取得
        MultiByteToWideChar CP_ACP, MB_PRECOMPOSED, varptr(text), -100  ; Shift_JIS 文字列を Unicode 文字列にした時の長さを取得
        unilen = stat                                                       ; これも文字数が返る(ヌル文字分含む)
        // Unicode に変換
        text2 = text                ; text 変数へ Unicode 文字列を入れるために Shift_JIS 文字列を別の変数に複製
        sdim text, unilen * 2       ; Unicode 文字列が入るだけの大きさで変数を作り直す
        unilen --                   ; ヌル文字分減らす
        cnvstow text, text2
        mes "\nファイルの内容 (ShiftJISからUnicodeに変換して表示) : "
    }

    // ファイルの内容を一部表示してみる
    rect = 0GINFO_CY640GINFO_CY + 16 * 3
    DrawTextW hdcvarptr(text), -1varptr(rect), DT_WORDBREAK|DT_EXPANDTABS
    pos , rect(3)

    // ファイル情報を表示
    mes "\nファイルサイズ:\n" + filesize + "byte"
    mes "\n文字数:\n" + unilen + "文字"
    mes "\n文字列のサイズ:\n" + (unilen * 2) + "byte"
    redraw

標準のHSPのファイルオープンダイアログ命令 dialog "", 16 で得られるファイルパスの文字コードは Shift_JIS なので、Win32API の GetOpenFileNameW から Unicode 用のファイルオープンダイアログを開いて、Unicode 文字列でファイルパスを取得しています。
ファイルの内容を取得する際も、HSP 標準の bload, noteload 命令には Shift_JIS 文字列のファイルパスしか渡せないため、API の CreateFileW で Unicode 文字列のファイルパスから ファイルを開き、これまた API の ReadFile で読み込んでいます。
テキストファイルの内容を取得した後も、その中身が同じ文字コードで書かれた文字列とは限らないため 中の文字コードによって処理を分けています。処理を分けるためにはそのテキストの文字コードの種類を判定する必要がありますが、それには API の IsTextUnicode 関数で実現できるようなので それを使って見ました(ネット上の C言語で書かれたいくつかのサンプルを見ながら書いて見ましたがいまいち使い方に自信が無い...(^^;))。
このスクリプトでは中のテキストの文字コードが Unicode ならそのまま、Shift_JIS なら Unicode に変換し、API の DrawTextW を使って Unicode 文字列を画面に表示しています。

・デスクトップにあるファイル名の一覧を Unicode で取得し表示する
#スクリプトは HSP3.4rc1 で実行確認しています

#include "user32.as"
#include "kernel32.as"
#include "gdi32.as"

#define MAX_PATH                    $00000104
#define DT_WORDBREAK                $00000010
#define DT_EXPANDTABS               $00000040
#define INVALID_HANDLE_VALUE        $FFFFFFFF
#define ERROR_NO_MORE_FILES         $00000012
#define FILE_ATTRIBUTE_DIRECTORY    $00000010
#define SW_SHOW                     $00000005
#define WS_CHILD                    $40000000
#define WS_VISIBLE                  $10000000
#define WS_BORDER                   $00800000
#define WS_VSCROLL                  $00200000
#define WS_HSCROLL                  $00100000
#define ES_MULTILINE                $00000004
#define ES_READONLY                 $00000800
#define WS_EX_CLIENTEDGE            $00000200
#define FW_NORMAL                   $00000190
#define DEFAULT_CHARSET             $00000001
#define OUT_DEFAULT_PRECIS          $00000000
#define CLIP_DEFAULT_PRECIS         $00000000
#define DEFAULT_QUALITY             $00000000
#define DEFAULT_PITCH               $00000000
#define FF_DONTCARE                 $00000000
#define WM_SETFONT                  $00000030
#define SYSTEM_FONT                 $0000000D

#define dwFileAttributes            0
#define nFileSizeLow                8
#define cFileName                   11


// ファイル列挙の準備
    // FindFirstFileW に必要な物の準備
    // WIN32_FIND_DATA は 320 byte だが、Unicode 版の WIN32_FIND_DATAW は 592 byte 必要
    dim fd, 148                                                 ; WIN32_FIND_DATAW 構造体分の領域確保
    sdim dir, MAX_PATH * 2
    cnvstow dir, DIR_DESKTOP + "\\*"                            ; FindFirstFileW に渡すフォルダ名を Unicode 文字列として用意

// ファイル列挙の開始
    // 検索ハンドルと最初のファイルを取得
    FindFirstFileW varptr(dir), varptr(fd)
    if stat = INVALID_HANDLE_VALUE {
        dialog "ファイル列挙開始のエラー"
        end
    }
    hfind = stat

    // ファイルリスト作成に必要な物の準備
    sdim filelist, (MAX_PATH * 2 + 64) * 256                    ; ファイル一覧の入る変数(予め十分なサイズを取る)
    sdim tmp, 64                                                ; 一時的に使う変数
    sdim ln, 64
    cnvstow ln, "\n"                                            ; 改行を Unicode 文字化する
    num = 0

    // ファイルリストを作る
    repeat
        // 取得ファイル(フォルダ)名を filelist に書き込む
        lstrcatW varptr(filelist), varptr(fd.cFileName)         ; filelist 末尾に fd.cFileName からの文字を書き込む

        // ファイルかフォルダかで処理を分ける
        if fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY {
            cnvstow tmp, "(フォルダ)"                         ; tmp にフォルダ表記を Unicode 文字列として格納
        } else {
            cnvstow tmp, strf("(%dバイト)", fd.nFileSizeLow)  ; tmp にファイルサイズを Unicode 文字列として格納
        }

        // ファイルリスト変数に改行区切りで追加
        // 取得したのがファイルならファイルサイズが、フォルダならフォルダ表記が書き込まれる
        lstrcatW varptr(filelist), varptr(tmp)                  ; filelist 末尾にファイル情報(サイズ、フォルダ)を書き込む
        lstrcatW varptr(filelist), varptr(ln)                   ; filelist 末尾に改行を書き込む

        // 次のファイルを取得
        FindNextFileW hfind, varptr(fd)
        if stat = 0 {                                           ; 処理の終了判定
            GetLastError
            if stat = ERROR_NO_MORE_FILES {                     ; ファイルが尽きたかエラーかを判定
                num = cnt + 1                                   ; 列挙数を格納
            } else {                                            ; エラーが起きたので終了する
                num = -1
            }
            break
        }
    loop

// ファイル列挙の終了
    // 検索ハンドルを閉じる
    FindClose hfind

    title "列挙数 : " + num
    if num < 0 {
        mes "次のファイルを取得のエラー"
        stop
    }


// 表示のしかたを切り替え可能
#if 0;1
// ウィンドウに直接ファイルリストを描画
    font MSGOTHIC16
    rect = 00GINFO_WINXGINFO_WINY : pos , rect(3)
    DrawTextW hdcvarptr(filelist), -1varptr(rect), DT_WORDBREAK|DT_EXPANDTABS
    redraw
#else
// HSPで言うところの mesbox を作成して、ファイルリストを表示
    // エディットコントロール作成
    style = WS_CHILD | WS_VISIBLE | ES_MULTILINE | WS_BORDER | WS_VSCROLL |WS_HSCROLL | ES_READONLY
    CreateWindowExW WS_EX_CLIENTEDGE, "EDIT"varptr(filelist), style, 00GINFO_WINXGINFO_WINYhwnd0hinstance0
    hedit = stat                                                ; コントロールのハンドル
    // エディットにフォントを設定
    sdim fontname, MAX_PATH * 2
    cnvstow fontname, MSGOTHIC                                  ; フォント名をユニコードにしておく
    pandf = DEFAULT_PITCH | FF_DONTCARE
    CreateFontW 16000, FW_NORMAL, 000, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, pandf, varptr(fontname)
    hfont = stat                                                ; フォントのハンドル
    SendMessageW hedit, WM_SETFONT, hfont, 1                    ; フォントを反映
// 一応最後にフォントを消去
    onexit *FIN
    stop
*FIN
    DeleteObject hfont
    end
#endif

列挙したデスクトップ上のファイル名の連結には Unicode のため a += b + "\n" とかは出来ないので、初めはサイズをチマチマ計算し memcpy 命令を使っての切り貼りで連結していましたが、lstrcatW と言う便利なAPI関数を発見してだいぶんスッキリ書くことが出来ました。
結果を表示するメッセージボックス(EDIT)も、HSP標準の物では Unicode 文字列を表示できないので、Unicode 対応のオブジェクト(コントロール)を、API の CreateWindowExW から作成しています。

・おまけで Unicode の表を表示。キーボードの上下左右キーでスクロール。
#スクリプトは HSP3.4rc1 で実行確認しています

#include "gdi32.as"

    start = 0
    fsize = 24
    xmax = GINFO_WINX / fsize
    ymax = GINFO_WINY / fsize
    font "メイリオ", fsize
    gosub *SUB_PRINT
    onkey gosub *ON_KEY
    stop

*ON_KEY
    if wparam >= 37 & wparam <= 40  {
        if wparam = 37  :page -= ymax
        if wparam = 39  :page += ymax
        if wparam = 38  :page--
        if wparam = 40  :page++
        gosub *SUB_PRINT
    }
    return

*SUB_PRINT
    redraw 0
    color 255255255  :boxf
    color
    repeat xmax * ymax
        x = cnt \ xmax
        y = cnt / xmax
        wpoke text, 0, start + cnt + page * xmax
        TextOutW hdc, x * fsize, y * fsize, varptr(text), 1
    loop
    redraw 1
    title ""strf("0x%04x ~ 0x%04x", (start + page * xmax) & 0xffff, (start + page * xmax + xmax * ymax) & 0xffff)
    return


ここまで作ってみて、やはり HSP から Unicode を扱うのはかなり面倒だという事が分かりました。HSPの命令は Unicode にはほぼ無力なので、手軽さが売りの HSP でやるには、APIを多用したり定数を定義したり、あまりにも面倒臭すぎます。。。

#調べながらなので間違い等あるかもしれません。
#HSPスクリプトの色分けには主に eller さん作の HTXcnv を使わせて頂きました。
  • [HSP3] つやつやギャラリー

サンプルスクリプト第一弾として、HSPコンテスト2009に応募して最終審査で落ちた(^^;)作品をほんの少し改善したものを掲載します。締め切り時間があと6時間くらいの所で、元々作って有った画像が回るスクリプトをベースに何とか形にした物なので、改善する余地はまだ幾分かありますけど。

「つやつやギャラリーv1.2」
#HSP3.2以降で実行してください
スクリプトのダウンロード


/*・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
    HSPコンテスト2009応募作品

    つやつやギャラリー Version 1.2
    作者 tyty
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・*/


    /* 初期化処理 */

    // ウィンドウタイトル設定
    title "つやつやギャラリー"

    // 変数初期化
    bg_r   = 255
    bg_g   = 255
    bg_b   = 255
    maxpix = 128
    ratio  = 0.0
    space  = 8
    max = 128
    x = (GINFO_WINX - maxpix) / 2
    y = (GINFO_WINY - maxpix) / 2

    // 配列変数初期化
    sdim files, 512, max
    dim posx, max
    dim posy, max
    dim order, max
    order = 0123456789
    ddim distance, max
    dim zx, max
    dim zy, max
    dim id, max
    dim margin, max

    // バッファー初期化

    /* 画像読み込み専用バッファー。
       ・サムネイル作成処理では、ここに一旦開いて、サイズ取得&サムネイル用バッファーに縮小コピーに使用
       ・クリック時の画像表示では、選択画像の読み込みに使用 */

    buffer 111

    // クリック時画像フェードに使うバッファーの初期化
    buffer 2640480          ; 暗くする時の色合成用
    buffer 3640480          ; 暗い状態から元に戻す為のメイン画像のコピー用

;・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・

    /* 画像ファイルリストの作成 */

    // 選んだ画像の置いてあるフォルダーを対象に
    dialog "jpg"16
    if stat = 0    :end

    gsel 0
    mes "読み込み中・・・"

    // 改行区切りのファイルリストを取得
    dirlist flist, "*.jpg"1
    fnum  = stat

    // 読み込み数の上限を10個までにする
    if fnum >= 10 { lim = 10   }
    else          { lim = fnum }

    // ファイルリストを改行で切り分けて、配列に格納する
    i = 0
    repeat lim
        getstr file, flist, i
        i += strsize
        files(cnt) = file
    loop

    /* ファイルリストを元に、サムネイル用の画像作成 */

    i = 0
    repeat lim

        // ファイルの存在確認
        exist files(cnt)
        if strsize < 0    :continue

        // 画像ファイルを開いて画像のサイズを取得
        gsel 1
        picload files(cnt)
        gx = GINFO_SX
        gy = GINFO_SY

        // 縦横比の計算
        if gx >= gy {
            ratio = double(gy) / gx
            zx(i) = maxpix
            zy(i) = int(ratio * maxpix)
            margin(i) = maxpix - zy(i)
        } else {
            ratio = double(gx) / gy
            zx(i) = int(ratio * maxpix)
            zy(i) = maxpix
            margin(i) = 0
        }

        // 新しいバッファーを作成
        buffer GINFO_NEWID, zx(i), zy(i)        ; リサイズ後の大きさで未使用バッファーを作成
        id(i) = GINFO_SEL                       ; 0要素目から順番にサムネイル用バッファーIDを入れていく

        // 新しいバッファーに、サイズ取得時に読み込んだ画像を縮小コピー
        gzoom zx(i), zy(i), 100, gx, gy, 1  ; サムネイル用にリサイズする
        i++

    loop

    // 使用済みバッファーを出来るだけ開放
    buffer 111

;・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・

    /* その他の設定 */

    gsel 0                      ; 描画先をメインウィンドウに
    randomize                   ; 乱数を不規則に
    onclick gosub *ON_CLICK     ; クリック時のジャンプを設定(選択画像の拡大)

;・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・

*MAIN

    // サムネイル画像の回転処理
    repeat

        redraw 0

        // 背景色を描画
        color bg_r, bg_g, bg_b
        boxf 00GINFO_WINXGINFO_WINY

        // ギャラリーの回転弧度を計算
        rad = 6.283 / 256 * cnt                 ; 一周するのに256ループ(手抜き)

        // 座標計算
        repeat lim
            tmp = rad + M_PI * 2 / lim * cnt    ; radをベースに各画像を等間隔で配置
            posx(cnt) = x + cos( tmp ) * x      ; tmpを元にX座標を計算
            posy(cnt) = y + sin( tmp ) * 32     ; tmpを元にY座標を計算
            distance(cnt) = sin( tmp ) + 1      ; ソート処理用に奥行きを計算
        loop

        // 奥行きを元に表示順をソーティング
        repeat lim
            i = cnt
            // 最大値を捜索
            repeat lim - (1 + cnt), 1 + cnt
                if distance(order(i)) > distance(order(cnt))    :i = cnt
            loop

            // 探した値同士を交換
            if cnt ! i {
                tmp = order(cnt)
                order(cnt) = order(i)
                order(i) = tmp
            }
        loop

        // 画面にサムネイル画像と映り込みを描画
        repeat lim
            // 使用する変数を用意
            i   = order(cnt)        ; 記述の簡略化のためにソート後のインデックスを代入
            ref = 1.75              ; 映り込み反射の長さ、2にすると半分になる(1.0~)

            // 画像本体を表示
            gmode 0
            pos posx(i), margin(i) + posy(i)
            gcopy id(i), 00, zx(i), zy(i)

            // 床の反射を表示
            repeat zy(i)
                gmode 3, zx(i), 1192.0 - (192.0 / zy(i) * (ref * cnt))
                pos posx(i), margin(i) + posy(i) + zy(i) + space + cnt
                gcopy id(i), 0, zy(i) - (ref * cnt)
            loop
        loop

        // どの画像の上にマウスポインタがあるかを調べる(secect変数に選択画像IDが入る)
        select = -1
        repeat lim
            // 奥行きの手前にある物から探す
            i = order(lim - cnt - 1)
            // マウスの位置から選択座標を判断
            if (mousex > posx(i)) & (mousex < posx(i) + zx(i)) {
            if (mousey > posy(i) + margin(i)) & (mousey < posy(i) + zy(i) + margin(i)) {
                    // 選択されていたら、選択画像の周りに枠を表示
                    boxsize = 4                                 ; ボックスの枠サイズ
                    color bg_r ^ 255, bg_g ^ 255, bg_b ^ 255    ; 背景色の補色
                    // 枠描画
                    boxf posx(i), posy(i) + margin(i), posx(i) + zx(i), posy(i) + margin(i) + boxsize
                    boxf posx(i) + zx(i) + 1, posy(i) + margin(i), posx(i) + zx(i) - boxsize, posy(i) + margin(i) + zy(i)
                    boxf posx(i) + zx(i), posy(i) + margin(i) + zy(i) + 1, posx(i), posy(i) + zy(i) + margin(i) - boxsize
                    boxf posx(i), posy(i) + margin(i), posx(i) + boxsize, posy(i) + margin(i) + zy(i)
                    select = i      ; 選択画像のIDを代入
                    break           ; 選択されていたらそこでループを抜ける
                }
            }
        loop

        redraw 1
        await 20

    loop

;・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・

/* クリック時のジャンプ先 */

*ON_CLICK

    // クリック時のズーム処理を何コマでアニメーションするか
    #define ANIME 10

    // 左クリックされた時の処理
    if wparam = 1 {

        // マウスの下に画像がある時だけ実行
        if select > -1 {
    
            /* クリックされた画像を大きく表示 */

            // 画像表示のための準備

            // 一時的にクリック無効化
            onclick 0

            // ファイルの存在確認
            exist files(select)
            if strsize < 0 {
                // エラー。クリックを有効化して、サブルーチンジャンプを抜ける
                dialog "ファイルが読み込めません"
                onclick 1
                return
            }

            // バッファーに画像読み込み、画像サイズの記憶
            gsel 1                              ; 画像読み込み用バッファー
            picload files(select)               ; マウスで選択したサムネイル画像のファイル名で開く
            gx = GINFO_SX
            gy = GINFO_SY

            // 縦横比の計算
            if gx >= gy {
                ratio = double(gy) / gx
                zx2   = 500
                zy2   = int(ratio * 500)
            } else {
                ratio = double(gx) / gy
                zx2   = int(ratio * 420)
                zy2   = 420
            }

            /* 画像を開く際のエフェクト */

            // 暗くする時のベース色
            gsel 2
            boxf                        ; 黒色でバッファーを塗りつぶす

            // 暗い状態から復帰するためのメイン画像のコピー
            gsel 3
            pos 00
            gcopy 000640480     ; サムネイル回転画面を複製

            // 暗くする
            gsel 0
            repeat ANIME1
                redraw 0
                gmode 3640480180 / ANIME
                pos 00
                gcopy 200
                redraw 1
                await 20
            loop

            // 画像ズームフェードから復帰するため、画面が暗くなった状態のメイン画面を複製
            gsel 2
            pos 00
            gcopy 000640480

            // 画像をズームしながら表示
            gsel 0
            gmode 0
            repeat ANIME1
                redraw 0
                pos (640 - zx2 / ANIME * cnt) / 2 , (480 - zy2 / ANIME * cnt) / 2
                gzoom zx2 / ANIME * cnt, zy2 / ANIME * cnt100, gx, gy, 1
                redraw 1
                await 15
            loop

            /* 画像のファイル名を表示 */

            // 文字の描画サイズを得るため、画面外にファイ名を表示
            redraw 0
            pos 6400
            mes files(i)

            // 画面の中央(X座標)に、袋文字の枠用ファイル名を表示
            color 0                 ; 袋文字の枠の色
            repeat 3  :_y = cnt
            repeat 3  :_x = cnt
                pos (640 - GINFO_MESX) / 2 + _x, 480 - GINFO_MESY - 3 + _y
                mes files(i)
            loop
            loop

            // 袋文字の中央に袋文字中身の文字を表示
            color 255255200     ; 袋文字の中の色
            pos (640 - GINFO_MESX) / 2 + 1480 - GINFO_MESY - 3 + 1
            mes files(i)
            redraw 1

            /* クリック待ち待機ループ */

            // 左クリックで復帰(何故か起動直後一回目のクリック判定がおかしいのでフラグで対処)
            flg = 0
            repeat
                await 100
                stick key
                if flg = 0       :key = 0    :flg++
                if key = 256     :break
            loop

            /* 画像を閉じる際のエフェクト */

            // 画像の縮小効果
            repeat ANIME1
                redraw 0
                pos 00
                gcopy 200640480
                pos (640 - zx2 / ANIME * (ANIME - cnt)) / 2 , (480 - zy2 / ANIME * (ANIME - cnt)) / 2
                gzoom zx2 / ANIME * (ANIME - cnt), zy2 / ANIME * (ANIME - cnt), 100, gx, gy, 1
                redraw 1
                await 15
            loop

            // 明るくする
            repeat ANIME1
                redraw 0
                gmode 3640480180 / ANIME * cnt
                pos 00
                gcopy 300
                redraw 1
                await 20
            loop

            /* 処理をメインに戻す前に後片付け */

            // 使用済みバッファーを出来るだけ開放
            buffer 111
            // メイン画面を描画先に
            gsel 0
            // 一時的なクリック無効化の解除
            onclick 1

        }

    }

    // 右クリックされた時の処理
    if wparam = 2 {

        /* 背景色の変更 */

        // 背景色の元をランダムに決定
        tmp = 2
        repeat 3
            r(cnt) = rnd(tmp + 1)       ; 0 ~ 2 の乱数を、赤、青、緑、分生成
        loop

        // 乱数からそれぞれの色成分を計算
        bg_r = r(0) * (256 / tmp) - (r(0) ! 0)      ; 背景色赤 : 0 or 127 or 255
        bg_g = r(1) * (256 / tmp) - (r(1) ! 0)      ; 背景色緑 : 0 or 127 or 255
        bg_b = r(2) * (256 / tmp) - (r(2) ! 0)      ; 背景色青 : 0 or 127 or 255

    }

    return

;・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。