では四回目を始めましょう。
今回は少し実用性のあるプログラムを作ってみます。
ショートカットファイルの「〜へのショートカット」という部分を削除するプログラムです。
第一回を参考にしてkcn04というプロジェクトとkcn04.cppというファイルを新規作成してください。
ファイルができたら下のソースコードをコピーして貼り付けてください。
では、ソースコードを 見てください。
#include <windows.h> #include <string.h> int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance , LPSTR lpCmdLine, int cmdShow) { char buf[MAX_PATH + 5]; char Dirbuf[MAX_PATH + 5]; LPTSTR lplink; WIN32_FIND_DATA fd; int i = lstrlen(lpCmdLine); lstrcpy(Dirbuf, lpCmdLine); for(int n=i ; n>0 ; n--) { if(Dirbuf[n] == '\\') { Dirbuf[n] = '\0'; break; } } FindFirstFile(lpCmdLine, &fd); wsprintf(buf, "%s\\%s", Dirbuf, fd.cFileName); lplink = strstr(buf, "へのショートカット.lnk"); if(lplink == NULL) return 0; lstrcpy(lplink, ".lnk"); MoveFile(lpCmdLine, buf); return 0; } ソースコード(コピー&ペースト用)
インクルードについてはもう説明の必要はありませんね。
今回は二つのヘッダファイルをインクルードしています。
さっそく内容に入りましょう。まずは
char buf[MAX_PATH + 5]; char Dirbuf[MAX_PATH + 5]; LPTSTR lplink; WIN32_FIND_DATA fd;
ですが最初にこの関数で使う変数を宣言しています。
C言語では変数はこの様に宣言してから使います。
ちなみに一つ目がファイル名を保存しておくバッファです。
少し大きめにとっておくのが強制終了を防ぐコツです。
二つ目がディレクトリ名を保存するバッファです。
三つ目が文字の場所を保存する変数です。
四つ目は検索して見つかったファイルのデータが保存される変数です。
次は
int i = lstrlen(lpCmdLine); lstrcpy(Dirbuf, lpCmdLine); for(int n=i ; n>0 ; n--) { if(Dirbuf[n] == '\\') { Dirbuf[n] = '\0'; break; } }
・・・う〜む、いきなり姑息なアルゴリズムを披露してしまった。
要するに
C:\windows\CALCへ~1.LNK
のようなファイルがドラッグアンドドロップ(以下D&D)された場合、ファイル名の後ろから
円記号'\'かどうかを一文字ずつチェックして円記号だった場合文字列の終わりという
目印'\0'を入れます。('\\'は'\'になります。)
すると
C:\windows
というディレクトリ名ができあがるというわけです。
次は
FindFirstFile(lpCmdLine, &fd);
FindFirstFile()関数は、第一引数で与えられたファイル名のファイルを
検索して、見つかったら
第二引数へそのファイルのデータをいろいろと格納します。
次は
wsprintf(buf, "%s\\%s", Dirbuf, fd.cFileName);
で最初に切り出したディレクトリ名と検索して取ってきたファイル名を連結します。
要するに
%s\\%s
の一つ目の%sをディレクトリ名(C:\windowsとか)に置き換えて、二つ目の%sを
ファイル名(Calcへのショートカット.lnkとか)に置き換えます。('\\'は'\'になります。)
C:\windows\Calcへのショートカット.lnk
そして置き換えた物をbufに保存します。
ちなみにfdという変数は「ファイルのデータをいろいろと格納する」と漠然と説明しましたが、
このfdの中にはファイル名をはじめファイルの大きさなど、変数が計10個も入っています。
そして
fd.cFileName
の様にして内部の変数を使うことができます。
実はこれが構造体と呼ばれる物で、このようにたくさんの情報をまとめて取得する場合などで
威力を発揮します。構造体なら
WIN32_FIND_DATA fd;
と書くだけで、見つかったファイルのデータを保存するための10個の変数が内部で用意されますが、
構造体がなければ自前で10個も変数を用意しなければならないでしょう。
構造体がどんなものかイメージが湧きましたか?湧いたら次へ進みましょう。
次は
lplink = strstr(buf, "へのショートカット.lnk");
です。このstrstr()関数は文字列の中の文字列を検索して見つかったらその場所を、
見つからなければNULLを返す関数です。ちなみにこの関数を使うためにstring.hを
インクルードしています。
そしてこの場合、文字列が見つかればlplinkにその場所が、見つからなければNULLが
lplinkに入るわけです。
C言語ではこの様に関数の戻り値を受け取って関数が成功したかどうかを判別します。
次は
if(lplink == NULL) return 0;
でlplinkの中身がNULLかどうか調べます。そしてNULLならその場で終了します。
NULLでなければ次へ進みます。
lstrcpy(lplink, ".lnk");
lplinkがNULLでなければlplinkが保存している場所に".lnk"を代入します。これで
「〜へのショートカット」が切り取れるわけです。
余談ですがこの場所を保存するlplinkという変数がC言語でもっともつまずきやすいと
言われているポインタです。
深く考えると難しくなるのでサクサク行きましょう。
そして最後に
MoveFile(lpCmdLine, buf); return 0;
です。MoveFile()関数はファイルを移動する関数ですがこの様にファイル名を変える場合にも
使われます。
第一引数に元のファイル名、第二引数に変えたいファイル名を入れます。
ファイル名の中のディレクトリを変更すれば移動する事になります。
ではビルドした後実行ファイルにショートカットファイルをドラッグ&ドロップしてみましょう。
ちゃんとファイル名が切り取れますね?
ちなみに今回のプログラムの約半分はショートファイル名をロングファイル名に直すという
作業をしています。それもかなり姑息な方法で(汗)
実はWindows98とNT5(Windows2000)以降ではGetLongPathName()という
ショートファイル名をロングファイル名に直す関数が使えます。
それを使用する場合はこんなソースになります。
今回はこれで終了です。今回は構造体やポインタが出てきましたね。
この辺は慣れるまでかなり手こずる部分です。行き詰まったら
参考書などで調べましょう。
では、お疲れさまでした。