ダブルクリックやメニューからプログラムを起動

ファイルがダブルクリックされたとき、拡張子に関連付けられたプログラムから起動します。
拡張子とプログラムの関連付けは、このプログラム独自のもので TEXT 形式のファイルから簡単に設定できます。
また List View で選択したファイルをメニュー選択でエディタなどから直接起動します。

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

Main プログラムの説明

  1. Main.rc に「エディタで編集」と「TabSet で変換」のメニューを追加します。
        POPUP "ツール(&T)"
        BEGIN
            MENUITEM "エディタで編集(&E)",          IDM_EDIT
            MENUITEM "TabSetで変換(&T)",            IDM_TBSET
        END
        
  2. Resource.h にメニューのIDを追加して下さい。
        #define IDM_LCOPYX      140
        #define IDM_RCOPYX      141
        #define IDM_EDIT        142
        #define IDM_TBSET       143
    
        #define IDD_DIALOG1     150
        #define IDC_EDIT1       151
        
  3. Main.cpp の修正です。
    プロセスの起動は winbase.h をインクルードして下さい。
    Filer Object Class の定義に拡張子とプログラムの関連付けを記述した TEXT ファイルの名前を指定します。
    TEXT ファイル(Fhand.dat)の記述の仕方はこのページの後で説明します。
        Filer       App("Fhand.dat");       //Filer Object Class 
        
  4. WM_COMMAND: に「エディタで編集」と「TabSetで変換」の処理を追加します。
    どちらも App.Process() を呼ぶだけです。
    今回は「右の List View」で選択されているファイルを起動してみましょう。
        case WM_COMMAND:
            switch(LOWORD(wp))
            {   case IDM_EDIT:       //選択ファイルを Editor で編集
                    App.Process(g_hListR,R_dir,0);
                    break;
                case IDM_TBSET:      //選択ファイルを TabSet で変換
                    App.Process(g_hListR,R_dir,1);
                    break;
        
  5. List View のアイテムがダブルクリックされたときの処理です。
    ダブルクリックされたのがファイルのとき ExecProc(cpDir,buf) で関連付けられたプログラムを起動します。
        case NM_DBLCLK:
            //カーソル位置から選択されたアイテムを探す
                      :
                //フォルダーか
                if (lvitem.lParam & FILE_ATTRIBUTE_DIRECTORY)
                {     :
                      :
                }
                else
                {   ListView_GetItemText(hList,lvhti.iItem,0,buf,64);
                    ExecProc(cpDir,buf);
                }
        


Filer Object Class の説明

  1. Filer Object Class Header(Filer.h) です。
    PCNT でメニューから提供するプログラムの数を定義します。
    si と pi はプロセスを起動するための領域です。
        #define     PCNT    2
    
        protected:
              :
          STARTUPINFO          si;
          PROCESS_INFORMATION  pi;
        
  2. ファイルがダブルクリックされたときに関連付けるプログラムと拡張子を格納する領域を定義します。
    関連付けのデータは、柔軟性を考慮してファイル(Fhand.dat)から入力します。
    PRGCNT は登録するプログラムの本数で、EXTCNT は関連付ける拡張子の個数です。
        #define     PCNT    2
    
        // Double Click Process Table
        char        Prog_T[20][80];
        struct
        {   char    ext[16];
            int     prg0,prg1;
        }   Ext_T[50];
        int         PRGCNT,EXTCNT;
        
  3. InitPrgTable() は拡張子とプログラムを関連付けるデータファイルを入力してテーブルに格納する関数です。
    Constructor にデータファイル名を受け取るパラメータを指定して下さい。
    Process() はプロセスを起動する関数(メソッド)の宣言です。
    ExecProc() はダブルクリックされたファイルに関連付けられたプログラムを起動する関数です。
          HRESULT     InitPrgTable(char file[]);
                          :
        public:
          Filer(char file[]);               //Constructor
          HRESULT     Process(HWND hList, char Dir[], int flag);
          HRESULT     ExecProc(char dir[],char fname[]);
        
  4. Filer.cpp の記述です。
    メニュー選択で起動するプログラムをフルパスで定義します。
    このテーブルに追加することで、簡単にプログラムメニューを増やすことができます。
        char        Prog[PCNT][80] =
                    {  "C:\\WINDOWS\\NOTEPAD.EXE ",
                       "C:\\Program Files\\WZ EDITOR\\wz_main.exe ",
                       "C:\\Bin\\TabSet.exe ",
                       "C:\\Bin\\DPIXED\\DPixed.exe ",
                       "C:\\Program Files\\Adobe\\Photoshop Elements\\PhotoshopElements.exe ",
                       "C:\\Program Files\\Adobe\\Photoshop 6.0\\Photoshop.exe ",
                    };
        
  5. Constructor から拡張子とプログラムを関連付けるデータをテーブルに格納する関数を呼びます。
        Filer::Filer(char file[])
        {      :
            InitPrgTable(file);
        }
        
  6. Process を起動する関数です。
    flag で起動するプログラムの番号を指定します。
    選択されているファイルを検索して CreateProcess() でプログラムを起動します。
        HRESULT  Filer::Process(HWND hList, char Dir[], int flag)
        {   char    sou[MAX_PATH];
            char    buf[64];
            int     nItem;
            LV_ITEM lvitem;
            HRESULT ret;
    
            if (ListView_GetSelectedCount(hList)==0)    return FALSE;
            nItem= -1;
            while(1)
            {   nItem = ListView_GetNextItem(hList,nItem,LVNI_ALL | LVNI_SELECTED);
                if (nItem == -1)    return TRUE;
                lvitem.mask= LVIF_PARAM;
                lvitem.iItem= nItem;
                lvitem.iSubItem= 0;
                if (!ListView_GetItem(hList,&lvitem))           continue;
                if (lvitem.lParam & FILE_ATTRIBUTE_DIRECTORY)   continue;
                ListView_GetItemText(hList,nItem,0,buf,64);
                strcpy(sou,Prog[flag]);
                strcat(sou,Dir);
                strcat(sou,buf);
                ret= CreateProcess(NULL,sou,NULL,NULL,FALSE,CREATE_NEW_PROCESS_GROUP|NORMAL_PRIORITY_CLASS,
                                   NULL,NULL,&si,&pi);
                if (ret==FALSE)     MessageBox(NULL,sou,"Process を起動できません",MB_OK);
            }
            return TRUE;
        }
        
  7. 拡張子とプログラムを関連付けるデータファイル(Fhand.dat)を入力してテーブルに格納する関数です。
    PRGCNT は登録するプログラムの個数で、最大20プログラムまで登録可能です。
    EXTCNT は関連付ける拡張子で、最大50個まで登録可能です。
    prg0 はプログラムの第一候補で、起動できなかったとき prg1(第二候補)で起動します。
        HRESULT Filer::InitPrgTable(char file[])
        {   HANDLE      hFile;
            DWORD       dwBytes;            //入力(出力)長
            char        buf[80];
            int         i,j;
    
            hFile= CreateFile(file,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
            if (hFile==INVALID_HANDLE_VALUE)
            {   MessageBox(NULL,"Fhand.dat  Open Error","READ DATA FILE",MB_OK);
                return FALSE;
            }
            while(1)
            {   ReadFile(hFile,buf,80,&dwBytes,NULL);
                if (buf[0]!='/')    break;
            }
            PRGCNT= atoi(buf);                  //登録するプログラム数
            EXTCNT= atoi(buf+4);                //登録する拡張子数
            for(i=0; i<PRGCNT; i++)
            {   ReadFile(hFile,buf,80,&dwBytes,NULL);
                //最後尾の空白位置を見つける
                for(j=75; j>0 && buf[j]==' '; j--);
                buf[j+2]= '\0';                 //一個の空白を確保
                strcpy(Prog_T[i],buf);
                if (j<=0)   Prog_T[i][0]= '\0'; //空(EXE)のとき
            }
            for(i=0; i<EXTCNT; i++)
            {   ReadFile(hFile,buf,80,&dwBytes,NULL);
                for(j=15; buf[j]==' '; j--);
                buf[j+1]= 0;
                strcpy(Ext_T[i].ext,buf);
                Ext_T[i].prg0= atoi(buf+16);
                Ext_T[i].prg1= atoi(buf+20);
            }
            CloseHandle(hFile);
            return TRUE;
        }
        
  8. ダブルクリックされたファイルに関連付けられたプログラムを起動する関数です。
        HRESULT  Filer::ExecProc(char dir[],char fname[])
        {   HRESULT ret;
            char    extw[6];
            int     i;
    
            extw[0]= 0;                             //拡張子を取り出す
            for(i=strlen(fname); i>0 && fname[i]!='.'; i--);
            if (i>0)    strcpy(extw,fname+i+1);
            for(i=0; Ext_T[i].ext[0]!='*' && strcmpi(Ext_T[i].ext,extw); i++);
            strcpy(w_dir,Prog_T[Ext_T[i].prg0]);    //prg0 で起動
            strcat(w_dir,"\"");
            strcat(w_dir,dir);
            strcat(w_dir,fname);
            strcat(w_dir,"\"");
            ret= CreateProcess(NULL,w_dir,NULL,NULL,FALSE,CREATE_NEW_PROCESS_GROUP|NORMAL_PRIORITY_CLASS,
                               NULL,NULL,&si,&pi);
            if (ret==TRUE)  return  TRUE;
            strcpy(w_dir,Prog_T[Ext_T[i].prg1]);    //prg1 で起動
            strcat(w_dir,"\"");
            strcat(w_dir,dir);
            strcat(w_dir,fname);
            strcat(w_dir,"\"");
            ret= CreateProcess(NULL,w_dir,NULL,NULL,FALSE,CREATE_NEW_PROCESS_GROUP|NORMAL_PRIORITY_CLASS,
                               NULL,NULL,&si,&pi);
            return ret;
        }
        


関連付けデータファイルの説明

ファイルの拡張子と起動するプログラムとの関連付けには、過去に何度も悩まされてきました。
そこで今回は思い切って関連付けそのものも自前で作成することにします。
拡張子とプログラムを関連付けるデータファイル(Fhand.dat)の例です。
プログラムと同じフォルダーに格納して下さい。
//File Handler Double Click Process    Size: 78byte + CR/LF = 80 Byte        
//Program Count(MAX 20)  &  Extent Count(MAX 50)                              
14  21                             0-3:ProgramCount  4-7:EXPCount             
C:\WINDOWS\NOTEPAD.EXE                                                       0
C:\Program Files\WZ EDITOR\wz_main.exe                                       1
C:\BIN\iview351j\i_view32.exe                                                2
C:\Program Files\Internet Explorer\IEXPLORE.EXE                              3
C:\Program Files\Windows Media Player\wmplayer.exe                           4
C:\BIN\SUSIE\Susie.exe                                                       5
C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin\MSDEV.EXE        6
C:\Program Files\Microsoft Office\Office\EXCEL.EXE                           7
C:\Program Files\Microsoft Office\Office\WINWORD.EXE                         8
C:\Program Files\Microsoft Office\Office\POWERPNT.EXE                        9
                                                                            10
C:\Jcpad\Jcpad.exe                                                          11
C:\Lcpad\Lcpad.exe                                                          12
D:\Program Files\Microsoft Visual Studio .NET\Common7\IDE\devenv.exe        13
BMP              002 002               0-15, 16-19, 20-23                    0
JPG                2   2                                                     1
GIF                2   2                                                     2
PNG                2   2                                                     3
HTM                3   3                                                     4
HTML               3   3                                                     5
MID                4   2                                                     6
WAV                4   2                                                     7
TIM                5   5                                                     8
MAG                5   5                                                     9
DSP                6   1                                                    10
DSW                6   1                                                    11
VCPROJ            13   1                                                    12
ICO                2   2                                                    13
XLS                7   7                                                    14
DOC                8   8                                                    15
PPT                9   9                                                    16
EXE               10  10                                                    17
JAVA              11  11                                                    18
C                 12  12                                                    19
*                  1   0                                                    20
  1. Fhand.dat はレコード長が80バイト(78+CR+LF)の固定長で作成します。
  2. 最初の // で始まる行はコメントです。ファイルの先頭に任意の行数を記述できます。
  3. コメント行の次に「登録するプログラムの本数と拡張子の個数」をタイプします。
    0カラムから3カラムの間にプログラムの本数を、4カラムから7カラムの間に拡張子の個数をタイプします。
    プログラムの本数と拡張子の個数の間には空白を空けて下さい。
    プログラムは最大20本まで登録可能です。(上の例では14本のプログラムを登録しています)
    拡張子は最大50個まで登録可能です。(上の例では21個の拡張子を登録しています)
  4. プログラムの本数で指示した実行プログラムの記述が続きます。
    拡張子に関連付けて起動するプログラムを76文字以内のフルパスで指定して下さい。
    行末の数字はコメントで、10 の行は見やすいように空行を設けています。
  5. 拡張子の個数で指示した関連付けが続きます。
    拡張子は16文字以内(普通は4文字以内)で指定して下さい。
    16カラムから19カラムの間に関連付けるプログラムの番号を指定します。
    続いて20カラムから23カラムの間に失敗したときに関連付けるプログラムの番号を指定します。
    25カラムから後はコメントです。レコード長は80バイトに揃えて下さい。
    最後の * は関連付けされていない拡張子のファイルを起動するときの指定です。
  6. 上の例では MID は、4(wmplayer.exe)に関連づけられています。
    wmplayer.exe が起動できないときは、2(i_view32.exe)が起動されます。
    関連付けが無いファイルは、1(wz_main.exe)で起動されます。
    wz_main.exe が起動できないときは、0(NOTEPAD.EXE)が起動されます。

[Next Chapter ↓] その他の機能を組み込む
[Previous Chapter ↑] コピーと削除機能を組み込む

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