プログラミングのメモ帳(C/C++/HSP)

日々のプログラミングで気づいた点や小技集を紹介します。(Windows 10/XP/Vista、VC2017、HSP)

[HSP]ディスク容量の取得(1)

2014年08月30日 19時18分00秒 | HSP講座

スクリプト言語の HSP については、公式ホームページの「HSPTV!」をどうぞ。(戻る)


ここでは、ハードディスクなどのディスク容量を取得する方法を紹介します。
API 関数については「ディスク容量の取得(1)」を参照して下さい。
ここに書かれた内容を HSP の呼び出し規則に従って書き直しモノが次の小技集です。
分かりやすくするために、あえてモジュールにしてません。

ディスク容量の共通ヘッダ - apiDrvUsageHead.as

#ifndef __APIDRVUSAGE__
#define __APIDRVUSAGE__

//--------------------------------------
// Win32API関数の命令登録
//--------------------------------------
#uselib "Kernel32.dll"
# func global SetErrorMode          "SetErrorMode"          sptr
#cfunc global GetDriveType          "GetDriveTypeA"         sptr
# func global GetDiskFreeSpace      "GetDiskFreeSpaceA"     sptr,var,var,var,var

//----------------------------------------------
// SetErrorModeの記号定数
//----------------------------------------------
#const SEM_FAILCRITICALERRORS           $00000001
#const SEM_NOALIGNMENTFAULTEXCEPT       $00000004
#const SEM_NOGPFAULTERRORBOX            $00000002
#const SEM_NOOPENFILEERRORBOX           $00008000

//----------------------------------------------
// GetDriveTypeの記号定数
//----------------------------------------------
#const DRIVE_UNKNOWN                    $00000000
#const DRIVE_NO_ROOT_DIR                $00000001
#const DRIVE_REMOVABLE                  $00000002
#const DRIVE_FIXED                      $00000003
#const DRIVE_REMOTE                     $00000004
#const DRIVE_CDROM                      $00000005
#const DRIVE_RAMDISK                    $00000006

//--------------------------------------
// 列挙定数(配列メンバ)
//--------------------------------------
#enum dbUsed=0                          ;使用容量(バイト)
#enum dbFree                            ;空き容量(バイト)
#enum dbTotal                           ;搭載容量(バイト)
#enum dbRatio                           ;使用率(%)
#enum SIZEOF_RESULT

//--------------------------------------
// 列挙定数(配列メンバ)
//--------------------------------------
#enum dwSector=0                        ;クラスタ当たりのセクタ数
#enum dwBytes                           ;1セクタ当たりのバイト数
#enum dwUnit                            ;クラスタ当たりのバイト数
#enum dwAvail                           ;空きクラスタ数
#enum dwTotal                           ;全クラスタ数
#enum SIZEOF_GETDISKFREESPACE

//--------------------------------------
// マクロ関数(変数参照)
//--------------------------------------
#define ctype GetDrvUsed                m_drv(dbUsed)
#define ctype GetDrvFree                m_drv(dbFree)
#define ctype GetDrvTotal               m_drv(dbTotal)
#define ctype GetDrvRatio               m_drv(dbRatio)
#
#define ctype GetDrvSector              m_sec(dwSector)
#define ctype GetDrvBytes               m_sec(dwBytes)
#define ctype GetDrvUnit                m_sec(dwUnit)

#endif
  • ディスク容量の取得で必要な API 関数の呼び出し定義です。
  • SetErrorMode と GetDriveType で必要な記号定数を定義してます。
  • 取得時に使う実数型の配列メンバと整数型の配列メンバを列挙定数で定義します。
  • ディスク容量の情報収集した変数(m_drv、m_sec)をマクロ関数で取得する仕組みです。

ディスク容量の取得 - apiDrvUsageTips.as

この apiDrvUsageTips.as には、次の2つのユーザ定義命令と1つのユーザ定義関数が含まれます。

//--------------------------------------
// ドライブ名で情報収集
//--------------------------------------
#deffunc GetDrvUsage int _drive_,\
    local szRoot,\
    local no
    
    no=_drive_
    if(no>='a'):no-='a'
    if(no>='A'):no-='A'
    if(no<26){
        szRoot="C:\\"
        poke szRoot,0,(no+'A')
        GetDrvUsagePath szRoot
        return stat
    }
    return 0
//--------------------------------------
// フルパス名で情報収集
//--------------------------------------
#deffunc GetDrvUsagePath str _path_
    ;変数確保
    ddim m_drv,SIZEOF_RESULT
    dim  m_sec,SIZEOF_GETDISKFREESPACE
    ;情報収集
    if(GetDriveType(_path_)==DRIVE_NO_ROOT_DIR)     :return 0
    GetDiskFreeSpace _path_,m_sec.dwSector,m_sec.dwBytes,m_sec.dwAvail,m_sec.dwTotal
    if(stat==0)or(m_sec.dwTotal==0)                 :return 0
    ;ディスク容量のセット
    m_sec(dwUnit)  = (m_sec.dwSector * m_sec.dwBytes)
    m_drv(dbTotal) = ClusterUnitBytes(m_sec.dwUnit,m_sec.dwTotal)
    m_drv(dbFree)  = ClusterUnitBytes(m_sec.dwUnit,m_sec.dwAvail)
    m_drv(dbUsed)  = (m_drv.dbTotal - m_drv.dbFree)
    m_drv(dbRatio) = (m_drv.dbUsed * 100 / m_drv.dbTotal)
    return
//--------------------------------------
// クラスタ数×ユニット量の計算
//--------------------------------------
#defcfunc ClusterUnitBytes int _p1_,int _p2_,\
    local p1,\
    local p2
    
    if(_p1_<0):p1=(4294967296.0+_p1_):else:p1=double(_p1_)
    if(_p2_<0):p2=(4294967296.0+_p2_):else:p2=double(_p2_)
    return (p1*p2)
  1. GetDrvUsage 命令
    • GetDrvUsage 命令でディスク容量の情報収集を行います。
    • この関数は 0~25、'A'~'Z'、'a'~'z'の3タイプでドライブを指定できるように工夫してます。
    • ルート・パスの文字列を作成したら GetDrvUsagePath 命令を呼び出します。
  2. GetDrvUsagePath 命令
    • GetDrvUsagePath 命令はパス指定で情報収集を行います。
    • この関数は「C:\」とか「H:\Develop\HSP\sample.hsp」というフルパス指定でもドライブを指定可能です。
    • 実数型配列(m_drv)は、dbUsed、dbFree、dbTotal、dbRatio の4つの要素を管理します。
    • 整数型配列(m_sec)は、dwSector、dwBytes、dwUnit、dwAvail、dwTotal の5つの要素を管理します。
    • GetDriveType 関数で無効なドライブかどうかをチェックしてます。
    • GetDiskFreeSpace 命令でドライブのディスク情報を取得します。
    • 戻り値が 0 でエラーか、dwTotal 要素が 0 ならばエラーと考えます。
    • その後にディスクのユニット量、搭載容量、空き容量、使用容量、使用率を計算します。
  3. ClusterUnitBytes 関数
    • ClusterUnitBytes 関数は、2つの引数を double 型に変換した後に乗算します。
    • この関数の内部で整数型を double 型にするためにゼロ以下とゼロ以上で処理を分けてます。
    • この処理を省くと 2 の 31 乗(231)を超える数値は、マイナス値として解釈されて正しく計算できません。

小技集のサンプル

次のサンプルで A ~ Z ドライブを一括で情報収集します。

//------------------------------------------------------------------------------
// ディスク容量の取得サンプル(1) by 科学太郎
//------------------------------------------------------------------------------
#include "apiDrvUsageHead.as"

//--------------------------------------
// メイン部
//--------------------------------------
*Init
    SetErrorMode SEM_FAILCRITICALERRORS
*Main
    n=16
    x=n*(2+9+9+9+5+5+5+5+1)
    y=n*(3+26+1)
    screen 0,x,y,SCREEN_NORMAL
    title "ディスク容量の取得サンプル(1)"
    font "HG明朝E",n
    repeat
        redraw 0
        ;画面クリア
        color $66,$99,$00:boxf
        color $00,$33,$00:pos 0,0
        ;罫線描画
        mes "┌─┬────────┬────────┬────────┬────┬────┬────┬────┐"
        mes "│No│    使用容量    │    空き容量    │    搭載容量    │ 使用率 │セクタ数│バイト数│ユニット│"
        mes "├─┼────────┼────────┼────────┼────┼────┼────┼────┤"
        repeat 26
            mes "│  │                │                │                │        │        │        │        │"
        loop
        mes "└─┴────────┴────────┴────────┴────┴────┴────┴────┘"
        ;画面描画
        pos 0,n*3
        repeat 26,'A'
            GetDrvUsage cnt
            if(stat):color $00,$33,$00:else:color $99,$CC,$00
            sdim msg
            msg+=strf(" %c:",cnt)                  ;ドライブ名
            msg+=strf(" %16.f",GetDrvUsed())       ;ドライブの使用容量(バイト)
            msg+=strf(" %16.f",GetDrvFree())       ;ドライブの空き容量(バイト)
            msg+=strf(" %16.f",GetDrvTotal())      ;ドライブの搭載容量(バイト)
            msg+=strf(" %6.2f%% ",GetDrvRatio())   ;ドライブの使用率(%)
            msg+=strf(" %8d",GetDrvSector())       ;クラスタ当たりのセクタ数
            msg+=strf(" %8d",GetDrvBytes())        ;1セクタ当たりのバイト数
            msg+=strf(" %8d",GetDrvUnit())         ;クラスタ当たりのバイト数
            mes msg
        loop
        redraw 1
        await 500
    loop
    stop
//--------------------------------------
// 小技集のインクルード
//--------------------------------------
#include "apiDrvUsageTips.as"
//------------------------------------------------------------------------------
// End of apiDrvUsageSample.hsp
//------------------------------------------------------------------------------
  • 最初に SetErrorMode 関数で SEM_FAILCRITICALERRORS を指定して実行しておきます。
  • これで CD-ROM ドライブにディスクが入ってなくてもエラー・ダイアログが出現しません。
  • GetDrvUsage 命令を実行してディスク容量の情報収集を行います。
  • あとは、それぞれのマクロ関数で情報収集した変数を読み出します。
    1. GetDrvUsed 関数でドライブの使用容量をバイト単位で取得
    2. GetDrvFree 関数でドライブの空き容量をバイト単位で取得
    3. GetDrvTotal 関数でドライブの搭載容量をバイト単位で取得
    4. GetDrvRatio 関数でドライブの使用率(%)を double 型で取得
    5. GetDrvSector 関数でドライブの1クラスタ当たりのセクタ数を取得
    6. GetDrvBytes 関数でドライブの1セクタ当たりのバイト数を取得
    7. GetDrvUnit 関数でドライブの1クラスタ当たりのバイト数を取得

スクリーン・ショット



コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« [HSP]クリップボードの操作... | トップ | [HSP]アナログ時計のソース... »
最新の画像もっと見る

コメントを投稿

HSP講座」カテゴリの最新記事