File Handler のフレームワークを作成する

List View, Edit Box, Tool Box, Status Bar を配置して、フレームワークを作成します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. 空の新規プロジェクト(Main)を作成します。
    プロジェクトのフォルダーに下記のファイルを作成(格納)して下さい。
    Main.cpp ソースプログラムファイル
    Main.rc リソースファイル
    Resource.h リソースのヘッダーファイル
    Filer.cpp Filer Object Class ソースファイル
    Filer.h Filer Object Class ヘッダファイル
    Copy.ico プログラムのアイコンファイル
    Tool.bmp Tool Bar のアイコン画像ファイル
  2. Tool.bmp は Tool Bar に表示するアイコン用の画像ファイルです。
    一個のアイコンは 16*16 ピクセルで 256 色モードで作成しています。
    黒色は 0,0,0 にしないで 8,8,8 ぐらいに設定して下さい。
    私は黒色のつもりで 0,0,0 に設定したのですが、色が透き通ってしまいました。

  3. リソースファイル(Main.rc)を自前で作成します。
    VC++ でリソースを定義すると非常に多くのソースコードが生成されますが、実際に必要なものは数行だけです。
    書かれている内容を見れば、大体理解できるでしょう。
        #include "resource.h"
    
        /////////////////////////////////////////////////////////////////////////////
        //
        // Icon
        //
    
        IDI_ICON1               ICON    DISCARDABLE     "Copy.ICO"
    
        /////////////////////////////////////////////////////////////////////////////
        //
        // Menu
        //
    
        IDR_MENU1 MENU DISCARDABLE 
        BEGIN
            POPUP "ファイル(&F)"
            BEGIN
                MENUITEM "アプリケーションの終了(&X)",  IDM_EXIT
            END
            POPUP "左側メニュー(&R)"
            BEGIN
                MENUITEM "強制コピー(&K)",              IDM_LCOPYX
                MENUITEM "フォルダーコピー(&Z)",          IDM_LCOPYZ
                MENUITEM "ファイルコピー(&C)",          IDM_LCOPY
                MENUITEM "ファイル削除(&D)",            IDM_LDEL
                MENUITEM "親フォルダーに移動(&P) ",       IDM_LPARENT
                MENUITEM "フォルダーの作成(&M) ",         IDM_LMKDIR
                MENUITEM "ドライブ変更(&V)",            IDM_LDRV
            END
            POPUP "右側メニュー(&L)"
            BEGIN
                MENUITEM "強制コピー(&K)",              IDM_RCOPYX
                MENUITEM "フォルダーコピー(&Z)",          IDM_RCOPYZ
                MENUITEM "ファイルコピー(&C)",          IDM_RCOPY
                MENUITEM "ファイル削除(&D)",            IDM_RDEL
                MENUITEM "親フォルダーに移動(&P) ",       IDM_RPARENT
                MENUITEM "フォルダーの作成(&M) ",         IDM_RMKDIR
                MENUITEM "ドライブ変更(&V)",            IDM_RDRV
            END
            POPUP "ヘルプ(&H)"
            BEGIN
                MENUITEM "バージョン情報(&A)",          IDM_ABOUT
            END
        END
    
        /////////////////////////////////////////////////////////////////////////////
        //
        // Bitmap
        //
    
        ID_BMP                BITMAP  DISCARDABLE     "tool.bmp"
        
  4. リソースのヘッダーファイル(Resource.h)も自前で作成して下さい。
    ID で定義する値は、重複しないように適当な値を設定します。
    Tool Bar のボタンの ID は IDM_LDRV から IDM_RDRV までを連番になるように設定して下さい。
    何を設定しても大抵うまく行くのですが、あまり変な値を設定すると思わぬことが起こるかも知れません。 (^_^;
    IDC_STATIC を宣言するときは、プログラムからは参照しないことを意味する値「-1」に設定します。
        //
        #define IDI_ICON1       4000
        #define IDR_MENU1       4001
        #define IDM_EXIT        4002
        #define IDM_LMENU       4003
        #define IDM_RMENU       4004
        #define IDM_ABOUT       4005
    
        #define ID_TOOLBAR      120
        #define IDM_LDRV        121
        #define IDM_LMKDIR      122
        #define IDM_LPARENT     123
        #define IDM_LDEL        124
        #define IDM_LCOPY       125
        #define IDM_LCOPYZ      126
        #define IDM_RCOPYZ      127
        #define IDM_RCOPY       128
        #define IDM_RDEL        129
        #define IDM_RPARENT     130
        #define IDM_RMKDIR      131
        #define IDM_RDRV        132
        #define ID_BMP          133
    
        #define IDM_LCOPYX      136
        #define IDM_RCOPYX      137
        
  5. Main.cpp と Filer.cpp と Filer.h はこの後で説明します。
  6. [プロジェクト][既存項目の追加]からファイルをプロジェクトに追加して、ビルドに続いて実行を行います。
    ページ先頭のウインドウが表示されたら完成です。 <(`^´)>


プログラムの説明

  1. Main.cpp のソースコードです。
    Windows のヘッダファイルは Filer Object Class のヘッダ(Filer.h)の中で取り込んでいます。
    Shell Object を使うので SHLOBJ.H を取り込んで comctl32.lib をリンクして下さい。
    List View と Status Bar と Edit Box の ID を定義します。
        #include    "Filer.h"
        #include    <SHLOBJ.H>
        #include    "resource.h"
        #pragma     comment(lib,"comctl32.lib")
    
        #define     ID_LISTVIEWL    100
        #define     ID_LISTVIEWR    101
        #define     ID_STATUS       102
        #define     ID_EDITL        103
        #define     ID_EDITR        104
        
  2. 「Filer App("Fhand.dat");」は Filer Object Class の定義です。
    List View, Status Bar, Edit Box, Tool Bar のハンドルを定義します。
        Filer       App("Fhand.dat");       //Filer Object Class 
        HINSTANCE   g_hInst;                //Instance Handle
        HWND        g_hWnd;                 //List Handle
        HWND        g_hListL;               //List Handle
        HWND        g_hListR;               //List Handle
        HWND        g_hToolBar;             //Tool Bar Handle
        HWND        g_hStatus;              //Status Bar Handle
        HWND        g_hEditC;               //Edit Box(Tool Bar)
        HWND        g_hEditR,g_hEditL;      //Edit Box Handle
        
  3. Tool Bar の定義です。
        TBBUTTON tbb[]=
        {   {0,  IDM_LMKDIR,  TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
            {1,  IDM_LPARENT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
            {2,  IDM_LDEL,    TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
            {3,  IDM_LCOPY,   TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
            {4,  IDM_LCOPYZ,  TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
            {5,  IDM_RCOPYZ,  TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
            {6,  IDM_RCOPY,   TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
            {7,  IDM_RDEL,    TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
            {8,  IDM_RPARENT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
            {9,  IDM_RMKDIR,  TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
        };
        
  4. 左右に表示する List View の Path です。
        char    L_dir[MAX_PATH]= "C:\\";
        char    R_dir[MAX_PATH]= "C:\\windows\\";
        
  5. WinMain() はいつもと同じです。
    WM_CREATE: の処理です。
    左右の List View を生成します。
    中央と左右の Edit Box を生成します。
    中央の Edit Box に Tool Bar を貼り付けます。
    Tool Bar を生成します。
    Status Bar を生成します。
    InitListView() で左右の List View にフォルダーを登録します。
    WS_DLGFRAME を含めると、List View の幅がある値より狭まらなくなります。
        case WM_CREATE:
            InitCommonControls();
            g_hListL = CreateWindowEx(0, WC_LISTVIEW, "",
                WS_CHILD | WS_VISIBLE | WS_DLGFRAME | LVS_EDITLABELS |
                LVS_REPORT | LVS_SHAREIMAGELISTS,
                0, 0, 0, 0, hWnd, (HMENU)ID_LISTVIEWL, g_hInst, NULL);
            g_hListR = CreateWindowEx(0, WC_LISTVIEW, "",
                WS_CHILD | WS_VISIBLE | WS_DLGFRAME | LVS_EDITLABELS |
                LVS_REPORT | LVS_SHAREIMAGELISTS,
                0, 0, 0, 0, hWnd, (HMENU)ID_LISTVIEWR, g_hInst, NULL);
            g_hEditC = CreateWindowEx(0, "EDIT", NULL, WS_CHILD | WS_VISIBLE,
                264, 2, 230, 28, hWnd, NULL, g_hInst, NULL);
            g_hEditL = CreateWindowEx(0, "EDIT", NULL,
                WS_CHILD | WS_VISIBLE | WS_DLGFRAME | ES_AUTOHSCROLL,
                3, 2, 260, 26, hWnd, (HMENU)ID_EDITL, g_hInst, NULL);
            g_hEditR = CreateWindowEx(0, "EDIT", NULL,
                WS_CHILD | WS_VISIBLE | WS_DLGFRAME | ES_AUTOHSCROLL,
                496, 2, 260, 26, hWnd, (HMENU)ID_EDITR, g_hInst, NULL);
            g_hToolBar= CreateToolbarEx(g_hEditC, WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS,
                ID_TOOLBAR, 12, g_hInst, ID_BMP, tbb,
                10, 0, 0, 16, 16, sizeof(TBBUTTON));
            App.InitListView(g_hListL,L_dir);
            App.InitListView(g_hListR,R_dir);
            SendMessage(g_hToolBar,TB_AUTOSIZE,0,0);
            g_hStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL,
                WS_CHILD|SBARS_SIZEGRIP|CCS_BOTTOM|WS_VISIBLE,
                0, 0, 0, 0, hWnd, (HMENU)ID_STATUS, g_hInst, NULL);
            break;
        
  6. WM_SIZE の処理です。
    List View のサイズなどは、ここで大きさが決まります。
        case WM_SIZE:
            w= LOWORD(lp);
            h= HIWORD(lp);
            MoveWindow(g_hEditC,w/2-115,2,230,28,TRUE);
            MoveWindow(g_hEditL,3,2,(w-236)/2,26,TRUE);
            MoveWindow(g_hEditR,w/2+115,2,(w-236)/2,26,TRUE);
            MoveWindow(g_hListL,2,30,(w-6)/2,h-50,TRUE);
            MoveWindow(g_hListR,w/2,30,(w-6)/2,h-50,TRUE);
            SendMessage(g_hStatus, WM_SIZE, wp, lp);
            parts[0]= w/2;
            SendMessage(g_hStatus, SB_SETPARTS, 2, (LPARAM)parts);
            break;
        


Filer.h の説明

  1. Filer.h のソースコードです。
    InitListView() は List View の初期化です。
    SetItem() は List View にフォルダーを設定して表示します。
    StaticMyCompProc(), MyCompProc(), SortItems() は List View をソートする関数です。
    //★ Filer Object Class Header   2003-08-08  前田 稔
    #include    <windows.h>
    #include    <commctrl.h>
    #define     UP      1
    #define     DOWN    2
    
    class Filer
    { //★非公開部分
      protected:
        HWND        g_hList;
        HIMAGELIST  hSmall;
        int         sortno[3];
        char        w_dir[MAX_PATH];
    
        static int  CALLBACK    StaticMyCompProc(LPARAM, LPARAM, LPARAM);
        int         CALLBACK    MyCompProc(LPARAM, LPARAM, LPARAM);
    
      //★公開部分
      public:
        Filer(char file[]);               //Constructor
        ~Filer();                         //Destructor
        void        InitListView(HWND hList, char dir[]);
        int         SetItem(HWND hList, char dir[]);
        void        SortItems(HWND hList, int col);
    };
        


Filer.cpp の説明

  1. Filer.cpp のソースコードです。
    Constructor では g_pApp に Filer Class のハンドルを設定して、List View のソートフラグを初期化します。
    //★ Filer Object Class    2003-08-10  前田 稔
    #include    "Filer.h"
    #include    
    
    Filer*      g_pApp = NULL;
    char        HEAD[][16]= {  "名前", "サイズ", "更新日付"  };
    int         CX[]=       {  160, 80, 140 };
    
    //★ Constructor
    Filer::Filer(char file[])
    {
        g_pApp = this;
        hSmall= NULL;
        sortno[0]=sortno[1]=sortno[2]= UP;
    }
    
    //★ Destructor
    Filer::~Filer()
    {   if (hSmall)    ImageList_Destroy(hSmall);
    }
        
  2. List View を初期化してフォルダーを登録するソースコードです。
    dir[] に表示するフォルダーを指定して、InitListView() を呼びます。
    List View への登録は Directry を List View に表示する を参照して下さい。
    //★ List View を初期化する
    void  Filer::InitListView(HWND hList, char dir[])
    {   LV_COLUMN       lvcol;
        int             i;
        SHFILEINFO      sfi;
    
        // ImageList の設定
        hSmall= (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\",0,&sfi,sizeof(SHFILEINFO),
                            SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
        if (hSmall)
            ListView_SetImageList(hList,hSmall,LVSIL_SMALL);
        // Column の項目設定
        lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
        lvcol.fmt = LVCFMT_LEFT;
        for(i=0; i<3; i++)
        {   lvcol.cx = CX[i];
            lvcol.pszText = HEAD[i];
            lvcol.iSubItem = i;
            ListView_InsertColumn(hList, i, &lvcol);
        }
        SetItem(hList,dir);
    }
    
    //★ CurrentDirectory を検索して List View に Item を設定する
    int Filer::SetItem(HWND hList, char dir[])
    {   WIN32_FIND_DATA fd;
        HANDLE          hFind;
        BOOL            bRet= TRUE;
        LV_ITEM         item;
        FILETIME        ft;
        SYSTEMTIME      sTime;
        int             i;
        char            buf[MAX_PATH];
        SHFILEINFO      sfi;
        LPSTR           lpPart;
    
        // dir の Full Directry を設定してカレントに設定する
        GetFullPathName(dir,MAX_PATH,w_dir,&lpPart);
        strcpy(dir,w_dir);
        if (SetCurrentDirectory(dir)==FALSE)
        {   if (dir[0]!='\0')   MessageBox(NULL,dir,"CurrentDirectry Error",MB_OK);
            strcpy(dir,"c:\\");
            SetCurrentDirectory(dir);
        }
        ListView_DeleteAllItems(hList);
        hFind= FindFirstFile("*.*",&fd);
        for(i=0; hFind!=INVALID_HANDLE_VALUE && bRet;)
        {   if (fd.cFileName[0] != '.')
            {   // フォルダー(ファイル)名を表示
                     :
                // フォルダー(ファイル)情報を取得
                     :
                // ファイルサイズを表示
                     :
                // 日付と作成時刻を表示
                     :
                i++;
            }
            bRet= FindNextFile(hFind,&fd);
        }
        FindClose(hFind);
        sortno[0]= UP;
        g_hList= hList;
        ListView_SortItems(hList,StaticMyCompProc,0);
        return i;
    }
        
  3. List View をソートするソースコードです。
    List View のソートは List View を Column でソートする を参照して下さい。
    //★ ITEM Sort 関数
    void  Filer::SortItems(HWND hList, int col)
    {
        if (sortno[col] == UP)    sortno[col] = DOWN;
        else                      sortno[col] = UP;
        g_hList= hList;
        ListView_SortItems(hList,StaticMyCompProc,col);
    }
    
    //★ Dummy 関数
    int  CALLBACK Filer::StaticMyCompProc(LPARAM lp1, LPARAM lp2, LPARAM lp3)
    {
        if (g_pApp)     return g_pApp->MyCompProc(lp1,lp2,lp3);
        return FALSE;
    }
    
    //★ Sub Item 比較関数
    int CALLBACK Filer::MyCompProc(LPARAM lp1, LPARAM lp2, LPARAM lp3)
    {       :
            :
    }
        

[Next Chapter ↓] Tool Bar の機能を設定する
[Previous Chapter ↑] File Handler を作成する

超初心者のプログラム入門(Win32API C++)