ショートカットのリンク先を一括変換する(32/64bit)

icon 項目のみ表示/展開表示の切り替え

概要

サーバーの交換やドライブ構成が変わった場合のショートカットの変更は面倒です。特に大量のパソコンがサーバーに接続されていると面倒です。
本プログラムは、定されたフォルダーに含まれる複数のショートカットのリンク先を変換します。変換パターンは2種類設定できます。
下図は、E:\tempに含まれるショートカットのリンク先がC:\であるものをD:\に変換する例です。

テスト環境

コンパイラ

Visual C++ 2008/2013 Express 32/64bit UNICODE

実行環境

Windows XP Professional Service Pack 3 32bit(Virtual Box上の仮想マシーン)
Windows 7 Enterprise Service Pack 1 64bit

プログラムソースの概要

shortcutchg.cpp

WinMain

 CoInitialize APIによりCOMを初期化します。
 ショートカットリンク先の変換ルールの初期設定をshortcutchg.iniから読み取るためにGetModuleFileName APIにより本プログラムのパスを取得します。
PathFindFileName APIによりファイル名を取り出し、フォルダー名のみを有効にします。
ダイアログボックスを呼び出します。
 CoUninitialize APIによりCOMを解放します。

DlgProc

WM_INITDIALOG
各コントロールのウィンドウハンドルを取得します。
shortcutchg.iniファイルより、初期ルールを呼び出します。
GetDesktopPath関数によりディスクトップのフォルダーを取得し、初期値とします。
WM_COMMAND
IDC_REF_BUTTON
参照ボタンをクリックすると呼び出されます。
GetDir関数によりフォルダ選択のコモンダイアログを表示し、フォルダ名を取得し、エディットボックスに設定します。
IDC_CHG_BUTTON
変換ボタンをクリックすると呼び出されます。
ショートカットを扱うための準備のため、IShellLink,IPersistFileの初期化を行う必要があります。
ここではshort_cut_initという関数を作成して呼び出しています。
エディットボックスからフォルダー名を取得します。
LVM_DELETEALLITEMSメッセージによりリストビューを初期化します。
変換ルールを読み込み配列にセットします。
get_dir_list関数により指定されたフォルダーにふくまれるショートカット(*.lnk)ファイルを検索し、リンク先の読み込み及び変更を行います。
ショートカットで使用したオブジェクトをshort_cut_exit関数で開放します。
IDCANCEL
キャンセルボタンをクリックした場合に呼び出されます。
EndDialog APIによりダイアロブボックスを終了させます。
short_cut_init
CoCreateInstance関数によりIShellLinkオブジェクトを作成します。 QueryInterface関数によりIPersistFileインターフェースの作成します。 複数のショートカットを扱う場合でも同時に1個しか扱わない場合は準備は1回で結構です。(STAでCOMを初期化しているのでスレッド単位で必要)
short_cut_exit
CoCreateInstance関数によりIShellLinkオブジェクトを作成します。 QueryInterface関数によりIPersistFileインターフェースの作成します。  複数のショートカットを扱う場合でも同時に1個しか扱わない場合は準備は1回で結構です。(STAでCOMを初期化しているのでスレッド単位で必要)
chg
get_dir_list関数から呼び出されます。
IPersistFileのメンバであるLoadにショートカットのファイル名を指定して呼び出すとショートカットが呼び出されます。
IShellLinkのメンバであるGetPathを呼び出すとリンク先が取得できます。
変換ルールをチェックして該当する場合、リンク先の文字列を変更します。
IPersistFileのメンバであるSaveでショートカットのファイル名を指定することによりショートカットが作成されます。
ListViewHeader
リストビューのヘッダーを初期化します。
get_dir_list
指定されたフォルダーからショートカットを検索し、見つかったショートカットに対してchg関数を呼び出します。
フォルダーが見つかった場合は、自分自身を呼び出してサブフォルダーを検索します。
GetDir
SHBrowseForFolderによりフォルダー名を取得するプログラム(32/64bit)を参照してください。
trim
_fgettsで取得された文字列から改行や復帰コードを除去します。
GetDesktopPath
ディスクトップのフォルダーを取得します。
第2引数を指定すると、マイドキュメントやお気に入り、スタートメニューを取得できます。

ソースコード

shortcutchg.cpp

//      指定されたフォルダーの複数のショートカットからリンク先を取得して表示後、変更する。
//      本プログラムと同じフォルダーにshortcutchg.iniファイルがある場合は、初期フォルダーと初期ルールを読み込む
//      Visual C++ 2008/2013 Express (UNICODE 32/64bit)

#include <windows.h>
#include <shobjidl.h>
#include <shlguid.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <stdio.h>
#include <tchar.h>
#include <commctrl.h>
#include "resource.h"

#pragma comment(lib,"shlwapi.lib")

int list_item_max=0;    //      検索されたショートカット数
int chg_short_cut=0;    //      変更されたショートカット数

IShellLink              *m_pShellLink=NULL;     
IPersistFile    *m_pPersistFile=NULL;

#define REPLACE_MAX 2   //      変換ルール個数

TCHAR src_str[REPLACE_MAX][MAX_PATH];   //      検索文字列
TCHAR dtc_str[REPLACE_MAX][MAX_PATH];   //      置換文字列

TCHAR exe_pass[MAX_PATH];       //      実行ファイルのパス
TCHAR* exe_name=0;      //      実行ファイルの名前

//      ダイアログボックスプロシージャー
LRESULT CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

// ショートカット関連のオブジェクト等の初期化
bool short_cut_init(IShellLink** m_pShellLink,IPersistFile** m_pPersistFile);

// ショートカット関連のオブジェクト等の解放
void short_cut_exit(IShellLink* m_pShellLink,IPersistFile* m_pPersistFile);

//      ファイル名よりショートカットの取得及び変更
TCHAR* chg(TCHAR* file_pass,TCHAR* pass,int sz,TCHAR* chg,int chg_sz);

//      リストビューヘッダーの初期化
void ListViewHeader(HWND hList);

//      フォルダーに含まれるショートカットをサブフォルダーも含めて検索する
int get_dir_list(HWND hList,HWND hStatus,TCHAR* pass,TCHAR* card);

//      ディレクトリ名を取得するダイアログを表示する
bool GetDir(HWND hWnd, TCHAR* def_dir,TCHAR* path);

//      特殊フォルダーを取得
void GetDesktopPath(TCHAR* path,int csidl=CSIDL_DESKTOPDIRECTORY);

//      不要な改行を削除
void trim(TCHAR* str);

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,LPSTR lpsCmdLine, int nCmdShow){

        if( FAILED( CoInitialize(NULL) )){      //      COMの初期化 STA(シングルスレッドアパートメント)
                MessageBox(0,_TEXT("COMの初期化に失敗しました"),_TEXT("エラー"),MB_OK);
                return -1;
        }

        GetModuleFileName(NULL,::exe_pass, sizeof(::exe_pass)/sizeof(TCHAR));   //      本プログラムのパスを取得
        ::exe_name=PathFindFileName(::exe_pass);        //      ファイル名の位置を取得
        *(::exe_name)=_T('\0');
//      ダイアログボックスの表示
        DialogBox(hCurInst, TEXT("DLG1"), 0, (DLGPROC)DlgProc);

        CoUninitialize();       //      COMの解放
        return (int)0;
}


//      ダイアログボックスプロシージャー

LRESULT CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){
        static HWND hEdit_dir;
        static HWND hList;
        static HWND hStatus;

        static TCHAR dir[MAX_PATH*40];          //      選択されたフォルダー名
        static TCHAR def_dir[MAX_PATH]; //      初期フォルダー

        static HCURSOR wait_icon=0;
        static HCURSOR org_icon=0;

        switch (msg) {
                case WM_INITDIALOG:{
                        wait_icon=LoadCursor(NULL,IDC_WAIT);    //      処理中アイコンの取得
                        hEdit_dir=GetDlgItem(hDlg,IDC_DIR_EDIT);
                        hList=GetDlgItem(hDlg,IDC_LISTVIEW);
                        hStatus=GetDlgItem(hDlg,IDC_STATUS_LABEL);
                        ListViewHeader(hList);
                        TCHAR fname[MAX_PATH];
                        TCHAR buf[MAX_PATH];
                        _stprintf_s(fname,sizeof(fname)/sizeof(TCHAR),_TEXT("%sshortcutchg.ini"),::exe_pass);
                        FILE* fp;
                        if( _tfopen_s(&fp,fname,_TEXT("r"))==0 ){ //      設定ファイルを読み込む
                                if(_fgetts(buf,sizeof(buf)/sizeof(TCHAR),fp)){
                                        trim(buf);
                                        SetWindowText(GetDlgItem(hDlg,IDC_SRC_EDIT1) , buf);
                                        if(_fgetts(buf,sizeof(buf)/sizeof(TCHAR),fp)){
                                                trim(buf);
                                                SetWindowText(GetDlgItem(hDlg,IDC_DTC_EDIT1) , buf);
                                                if(_fgetts(buf,sizeof(buf)/sizeof(TCHAR),fp)){
                                                        trim(buf);
                                                        SetWindowText(GetDlgItem(hDlg,IDC_SRC_EDIT1+1) , buf);
                                                        if(_fgetts(buf,sizeof(buf)/sizeof(TCHAR),fp)){
                                                                trim(buf);
                                                                SetWindowText(GetDlgItem(hDlg,IDC_DTC_EDIT1+1) , buf);
                                                        }
                                                }
                                        }
                                }
                                fclose(fp);
                        }
                        TCHAR desktop[MAX_PATH];
                        GetDesktopPath(desktop);
                        SetWindowText(hEdit_dir,desktop);       //      エディットボックスの中身をディスクトップにする

                        return TRUE;
                }
                case WM_COMMAND:
                        switch (LOWORD(wParam)) {
                                case IDC_REF_BUTTON:    //      参照ボタンをクリックした場合
                                        _tcscpy_s(def_dir,sizeof(def_dir)/sizeof(TCHAR),_TEXT("C:\\"));
                                        if(GetDir(hDlg,def_dir,dir)==TRUE){
                                                SetWindowText(hEdit_dir,dir);
                                        }
                                        break;
                                case IDC_CHG_BUTTON:{   //      変換ボタンをクリックした場合
                                        SetCursor(wait_icon);
                                        if(short_cut_init(&m_pShellLink,&m_pPersistFile)==false){
                                                MessageBox(0,_TEXT("com error"),_TEXT("エラー"),MB_OK);
                                                EndDialog(hDlg,TRUE);
                                        }
                                        GetWindowText(hEdit_dir,dir,sizeof(dir)/sizeof(TCHAR));
                                        SendMessage(hList,LVM_DELETEALLITEMS,0,0); // リストビュー全アイテム消去
//      変換ルールの読み込み
                                        for(int n=0;n<REPLACE_MAX;n++){
                                                HWND hSrc=GetDlgItem(hDlg,IDC_SRC_EDIT1+n);
                                                HWND hDtc=GetDlgItem(hDlg,IDC_DTC_EDIT1+n);
                                                GetWindowText(hSrc,::src_str[n],MAX_PATH);
                                                GetWindowText(hDtc,::dtc_str[n],MAX_PATH);
                                        }
                                        ::src_str[REPLACE_MAX][0]=0;
                                        ::dtc_str[REPLACE_MAX][0]=0;
                                        ::list_item_max=0;      //      ショートカット数のリセット
                                        ::chg_short_cut=0;      //      変更されたショートカット数のリセット
//      ショートカットの検索・表示・変更
                                        get_dir_list(hList,hStatus,dir,_TEXT("*.lnk"));

                                        short_cut_exit(m_pShellLink,m_pPersistFile);

                                        TCHAR buf[MAX_PATH+256];
                                        _stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),_TEXT("結果: ショートカット %d個,変換ショートカット %d個"),::list_item_max,::chg_short_cut);
                                        SetWindowText(hStatus,buf);

                                        SetCursor(org_icon);
                                        break;
                                }
                                case IDCANCEL:  //      キャンセルボタンをクリックした場合
                                        EndDialog(hDlg,TRUE);
                                        return TRUE;
                                default:
                                        return FALSE;
                        }
                        default:
                                return FALSE;
        }
        return TRUE;
}


// ショートカット関連のオブジェクト等の初期化

bool short_cut_init(IShellLink** m_pShellLink,IPersistFile** m_pPersistFile){
        if(CoCreateInstance( CLSID_ShellLink , NULL , CLSCTX_INPROC_SERVER ,IID_IShellLink ,(LPVOID *)m_pShellLink)==S_OK){
                if((*m_pShellLink)->QueryInterface( IID_IPersistFile, (LPVOID *)m_pPersistFile )==S_OK){
                        return true;
                }
                (*m_pShellLink)->Release();
                *m_pShellLink=0;
                *m_pPersistFile=0;
                return false;
        }
        *m_pShellLink=0;
        *m_pPersistFile=0;
        return false;
}

// ショートカット関連のオブジェクト等の解放

void short_cut_exit(IShellLink* m_pShellLink,IPersistFile* m_pPersistFile){
        m_pPersistFile->Release();
        m_pShellLink->Release();
}

//      ファイル名よりショートカットの取得及び変更

TCHAR* chg(TCHAR* file_pass,TCHAR* pass,int sz,TCHAR* chg,int chg_sz){
        if(m_pPersistFile->Load( file_pass, STGM_READ | STGM_SHARE_DENY_WRITE)==S_OK){
                m_pShellLink->GetPath(pass,sz,NULL,SLGP_UNCPRIORITY);        // UNCパス名を取得
                chg[0]=_T('\0');
                for(int n=0;n<REPLACE_MAX;n++){
                        TCHAR* find=::src_str[n];
                        TCHAR* replace=::dtc_str[n];
                        int len=(int)_tcslen(find);
                        if(len==0)
                                break;
                        if(_tcsncmp(pass,find,len)==0){
                                _tcscpy_s(chg,chg_sz,replace);
                                _tcscat_s(chg,chg_sz,pass+len);
                                m_pShellLink->SetPath(chg);  //      リンク先の設定
                                m_pPersistFile->Save(file_pass,TRUE);        //      ショートカットを保存する
                                ::chg_short_cut++;      //      変更されたショートカット数のカウントアップ
                                break;
                        }
                }
        }
        return pass;
}

//      リストビューヘッダーの初期化

void ListViewHeader(HWND hList){
        LV_COLUMN lvcol;
        lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
        lvcol.fmt = LVCFMT_LEFT;
        lvcol.cx = 192;
        lvcol.pszText = _TEXT("ショートカット名");
        lvcol.iSubItem = 0;
        ListView_InsertColumn(hList, 0, &lvcol);

        lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM ;
        lvcol.fmt =  LVCFMT_LEFT;
        lvcol.cx = 192;
        lvcol.pszText = _TEXT("フルパス");
        lvcol.iSubItem = 1;
        ListView_InsertColumn(hList, 1, &lvcol);

        lvcol.cx = 192;
        lvcol.pszText = _TEXT("リンク先変換前");
        lvcol.iSubItem = 2;
        ListView_InsertColumn(hList, 2, &lvcol);

        lvcol.cx = 192;
        lvcol.pszText = _TEXT("リンク先変換後");
        lvcol.iSubItem = 3;
        ListView_InsertColumn(hList, 3, &lvcol);
}

//      フォルダーに含まれるショートカットをサブフォルダーも含めて検索する

int get_dir_list(HWND hList,HWND hStatus,TCHAR* pass,TCHAR* card){
        WIN32_FIND_DATA FindFileData;
        HANDLE hFind;
        TCHAR find_pass[MAX_PATH];
        TCHAR find_top_pass[MAX_PATH];
        TCHAR sub_pass[MAX_PATH];
        TCHAR make_pass[MAX_PATH];
        static TCHAR buf[MAX_PATH+256];

        _stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),_TEXT("検索中:%s"),pass);
        SetWindowText(hStatus,buf);

        int num=0;      //      見つかったファイル数
        int l=(int)_tcslen(pass);
        int c=pass[l-1];        //      パスの最後の文字
        _tcscpy_s(find_top_pass,sizeof(find_top_pass)/sizeof(TCHAR),pass);
        if(c!=_T('\\') && c!=_T(':')){
                find_top_pass[l]=_T('\\');
                find_top_pass[l+1]=_T('\0');
        }

        _stprintf_s(find_pass,sizeof(find_pass)/sizeof(TCHAR),_TEXT("%s*.*"),find_top_pass);  //      サブディレクトリの検索
        hFind = FindFirstFile(find_pass, &FindFileData);
        if(hFind != INVALID_HANDLE_VALUE){
                do{
                        if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)==0 && (FindFileData.dwFileAttributes &FILE_ATTRIBUTE_READONLY )==0 )
                                if(_tcscmp(FindFileData.cFileName,_TEXT("..")) && _tcscmp(FindFileData.cFileName,_TEXT(".")) ){     //      親ディレクトリは無視する
                                        _stprintf_s(sub_pass,sizeof(sub_pass)/sizeof(TCHAR),_TEXT("%s%s"),find_top_pass,FindFileData.cFileName);                              
                                        num+=get_dir_list(hList,hStatus,sub_pass,card); //      サブディレクトリの中を検索
                                }
                }while( FindNextFile(hFind,&FindFileData) );
        }
        FindClose(hFind);
        int pass_len=(int)_tcslen(find_top_pass)+1;
        _stprintf_s(find_pass,sizeof(find_pass)/sizeof(TCHAR),_TEXT("%s%s"),find_top_pass,card);      //      ファイルの検索
        hFind = FindFirstFile(find_pass, &FindFileData);
        if(hFind != INVALID_HANDLE_VALUE){
                do {
                        if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0  && (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)==0 && (FindFileData.dwFileAttributes &FILE_ATTRIBUTE_READONLY )==0){
                                ++num;
                                _stprintf_s(make_pass,sizeof(make_pass)/sizeof(TCHAR),_TEXT("%s%s"),find_top_pass,FindFileData.cFileName);

                                TCHAR full[MAX_PATH];
                                TCHAR* file;
                                GetFullPathName(make_pass,sizeof(full)/sizeof(TCHAR),full,&file);

                                LV_ITEM item;
                                item.mask = LVIF_TEXT  | LVIF_PARAM;
                                item.pszText =file;
                                item.iItem = ::list_item_max;
                                item.iSubItem = 0;
                                item.lParam = ::list_item_max;
                                ListView_InsertItem(hList, &item);

                                item.mask = LVIF_TEXT;
                                item.pszText =full;
                                item.iItem = ::list_item_max;
                                item.iSubItem = 1;
                                ListView_SetItem(hList, &item);

                                TCHAR src_pass[MAX_PATH];
                                TCHAR dtc_pass[MAX_PATH];
                                chg(full,src_pass,sizeof(src_pass)/sizeof(TCHAR),dtc_pass,sizeof(dtc_pass)/sizeof(TCHAR));
                                
                                item.mask = LVIF_TEXT;
                                item.pszText =src_pass;
                                item.iItem = ::list_item_max;
                                item.iSubItem = 2;
                                ListView_SetItem(hList, &item);

                                item.mask = LVIF_TEXT;
                                item.pszText =dtc_pass;
                                item.iItem = ::list_item_max;
                                item.iSubItem = 3;
                                ListView_SetItem(hList, &item);

                                ::list_item_max++;

                        }
                }while( FindNextFile(hFind,&FindFileData) );
                return num;
        }else
                return num;
}


//      ディレクトリ名を取得するダイアログを表示する
//      GetDir(親ウィンドウのハンドル,初期時選択フォルダー,選択されたフォルダー名);
//      trueが返された場合有効なフォルダー名が取得できた場合

int __stdcall BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);


bool GetDir(HWND hWnd, TCHAR* def_dir,TCHAR* path){
        BROWSEINFO bInfo;
        LPITEMIDLIST pIDList;

        memset(&bInfo,0,sizeof(bInfo));
        bInfo.hwndOwner = hWnd; // ダイアログの親ウインドウのハンドル 
        bInfo.pidlRoot = NULL; // ルートフォルダをデスクトップフォルダとする 
        bInfo.pszDisplayName = path; //フォルダ名を受け取るバッファへのポインタ 
        bInfo.lpszTitle = TEXT("フォルダの選択"); // ツリービューの上部に表示される文字列 
        bInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX | BIF_VALIDATE | BIF_NEWDIALOGSTYLE; // 表示されるフォルダの種類を示すフラグ 
        bInfo.lpfn = BrowseCallbackProc; // BrowseCallbackProc関数のポインタ 
        bInfo.lParam = (LPARAM)def_dir;
        pIDList = SHBrowseForFolder(&bInfo);
        if (pIDList == NULL){
                path[0] = _TEXT('\0');
                return false; //何も選択されなかった場合 
        }
        else{
                if (!SHGetPathFromIDList(pIDList, path))
                        return false;//変換に失敗 
                CoTaskMemFree(pIDList);// pIDListのメモリを開放 
                return true;
        }
}
//      上記ダイアログのコールバック関数

int __stdcall BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData){
        TCHAR dir[MAX_PATH];
        ITEMIDLIST *lpid;
        HWND hEdit;

        switch (uMsg){
        case BFFM_INITIALIZED:  //      ダイアログボックス初期化時
                SendMessage(hWnd, BFFM_SETSELECTION, (WPARAM)TRUE, lpData);     //      コモンダイアログの初期ディレクトリ
                break;
        case BFFM_VALIDATEFAILED:       //      無効なフォルダー名が入力された
                MessageBox(hWnd,(TCHAR*)lParam,_TEXT("無効なフォルダー名が入力されました"),MB_OK);
                hEdit=FindWindowEx(hWnd,NULL,_TEXT("EDIT"),NULL);     //      エディットボックスのハンドルを取得する
                SetWindowText(hEdit,_TEXT(""));
                return 1;       //      ダイアログボックスを閉じない
                break;
        case BFFM_IUNKNOWN:
                break;
        case BFFM_SELCHANGED:   //      選択フォルダーが変化した場合
                lpid=(ITEMIDLIST *)lParam;
                SHGetPathFromIDList(lpid,dir);
                hEdit=FindWindowEx(hWnd,NULL,_TEXT("EDIT"),NULL);     //      エディットボックスのハンドルを取得する
                SetWindowText(hEdit,dir);
                break;
        }
        return 0;
}

//      不要な改行を削除

void trim(TCHAR* str){
        TCHAR* p=str;
        while(*p){
                switch(*p){
                        case _T('\n'):
                        case _T('\r'):
                                *p=_T('\0');
                                return;
                }
                ++p;
        }
}

//      特殊フォルダーを取得
//      csidl=CSIDL_DESKTOPDIRECTORY    ディスクトップ
//      csidl=CSIDL_PERSONAL    マイドキュメント
//      csidl=CSIDL_FAVORITES   お気に入り
//      csidl=CSIDL_STARTMENU   スタートメニュー

void GetDesktopPath(TCHAR* path,int csidl){
        LPITEMIDLIST pidl;
        HWND hWnd = NULL;
        IMalloc *pMalloc;
        SHGetMalloc( &pMalloc );
        if( SUCCEEDED(SHGetSpecialFolderLocation(hWnd,csidl,&pidl)) ){
                // パスに変換する
                SHGetPathFromIDList(pidl,path);
                // 取得したIDLを解放する (CoTaskMemFreeでも可)
                pMalloc->Free(pidl);
        }
        pMalloc->Release();
        return;
}

resource.h

#define IDC_DIR_EDIT            100
#define IDC_REF_BUTTON          110
#define IDC_SRC_EDIT1           120
#define IDC_DTC_EDIT1           130
#define IDC_LISTVIEW            140
#define IDC_CHG_BUTTON          150
#define IDC_STATUS_LABEL        160

#define APL_NAME "ショートカットリンク先一括変換"
#define APL_NAME0 "ショートカットリンク先一括変換\0"
#define FILE_VERSION 1,0,0,0
#define VERSION_NUMBER  "1, 0, 0,0"
#define VERSION_NUMBER0 "1, 0, 0,0\0"
#define COPYRIGHT "Copyright (C) 2014/08/27"
#define COPYRIGHT0 "Copyright (C) 2014/08/27"
#define DESCRIPTION  "キラー"
#define DESCRIPTION0  "キラー\0"
#define APL_VER "ショートカットリンク先一括変換 Version  1, 0, 0,0"

resource.rc

#include <windows.h>
#include "resource.h"

IDI_ICON        ICON    DISCARDABLE     "org.ico"

DLG1 DIALOG DISCARDABLE 0, 0, 460, 387
EXSTYLE WS_EX_DLGMODALFRAME
STYLE WS_POPUP  | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | DS_SETFONT
CAPTION "ショートカットリンク先一括変換"
FONT 9, "MS 明朝"
{
 CONTROL "変換対象フォルダー", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 7, 14, 103, 14

 CONTROL "C:\\", IDC_DIR_EDIT, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 14, 28, 378, 14
 CONTROL "参照", IDC_REF_BUTTON, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 399, 28, 47, 14

 CONTROL "リンク先変換ルール", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 7, 56, 96, 14
 CONTROL "ルール1", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 14, 71, 48, 14

 CONTROL "", IDC_SRC_EDIT1, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 62, 69, 173, 14
 CONTROL "→", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 250, 71, 16, 14
 CONTROL "", IDC_DTC_EDIT1, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 273, 69, 173, 14

 CONTROL "ルール2", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 14, 93, 48, 14
 CONTROL "", IDC_SRC_EDIT1+1, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 62, 91 173, 14
 CONTROL "→", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 250, 93, 16, 14
 CONTROL "", IDC_DTC_EDIT1+1, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 273, 91,173, 14

 CONTROL "変換結果", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 7, 119, 60, 14
 CONTROL "ListView110", IDC_LISTVIEW, "SYSLISTVIEW32", WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT, 14, 133, 432, 184
 
 CONTROL "", IDC_STATUS_LABEL, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 7, 331,439, 28

 CONTROL "変換", IDC_CHG_BUTTON, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 169, 359, 54, 18
 CONTROL "キャンセル", IDCANCEL, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 237, 359, 54, 18

}

//--------------------
//  ヴァージョン情報
//--------------------

VS_VERSION_INFO VERSIONINFO
 FILEVERSION FILE_VERSION
 PRODUCTVERSION FILE_VERSION
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "Comments", APL_NAME0
            VALUE "CompanyName",DESCRIPTION0
            VALUE "FileDescription", APL_NAME0
            VALUE "FileVersion", VERSION_NUMBER0 
            VALUE "InternalName", "\0"
            VALUE "LegalCopyright", COPYRIGHT0
            VALUE "OriginalFilename", "shortcutchg.exe\0"
            VALUE "ProductName", APL_NAME0
            VALUE "ProductVersion",  VERSION_NUMBER0 
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation",0x0411, 0x03A4 
    END
END

実行ファイルとソースファイルのダウンロード