Delphi Tips
>> Index
● 01/22 短いファイル名を長いファイル名に変換したい(COM版)。
● 12/31 リンクファイルから参照先のファイル名を得る
● 06/27 ファイルの更新日時を得る
● 06/25 FindFirst でアイコンを変更したディレクトリを検索できない
● 06/25 FindFirst による4文字以上の拡張子の判別
● 05/14 ディレクトリのファイルを列挙する
● 09/27 短いファイル名を長いファイル名に変換したい。
● 09/27 エクスプローラからファイルをドラッグ&ドロップする
● 09/26 ファイルを削除してゴミ箱に移動させたい。
● 09/24 Windows 特殊フォルダの Class ID List
● 09/22 長いファイル名を短いファイル名に変換したい
● 09/08 任意のドライブをセクタ単位で読み書きする
● 09/08 フォルダのタイムスタンプを変更する
● 08/26 他のアプリの起動パスを取得する
● 02/11 カレントユーザのデスクトップディレクトリを得る
● 02/11 TFileStream で標準出力に表示
● 02/11 エクスプローラで使われるアイコンを取得・変更する
● 02/11 クリップボードにコピーされたファイル・ディレクトリ
● 02/11 リムーバブルドライブの種類を判別する
● 02/08 リードオンリーファイルを Assign/Reset で読もうとするとエラーになる
● 02/08 複数プログラムから同一内容のメモリを参照/更新する
● 02/08 OpenDialogでたくさんファイルを選択するとエラー
● 02/08 TDriveComboBoxの内容の更新
● 02/08 NTで他のアプリが開いているファイルを知る
最終更新: 6880 日前
0273 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/09/24 西坂良幸 rev 1.3 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 2006/01/22 <> 編集
短いファイル名を長いファイル名に変換したい(COM版)。
エクスプローラは内部的には、短い名前を使っているようです。
ということは、シェルのCOMインターフェースのメソッドが使えるということです。
[Tips:233]のCOM版を考えてみましょう。
uses ShlObj,Comobj,ActiveX;
function ShortToLongFileName(const ShortName: string): string;
var
Desktop: IShellFolder;
pIDList: PITEMIDLIST;
NameS: String;
NameW: WideString;
Len : integer;
Buffer: array[0..MAX_PATH] of Char;
// 以下は値は使わない
pDummy: PCHAR;
pchEaten, Attributes: ULONG;
begin
pIDList := Nil;
// フルパス化
Len := GetFullPathName(PChar(ShortName), 0, PChar(result), pDummy);
SetLength(NameS, Len);
GetFullPathName(PChar(ShortName), Len, PChar(NameS), pDummy);
// ワイド文字列に転換
NameW := NameS;
// IShellFolderを生成(解放は自動)
OleCheck(SHGetDesktopFolder(Desktop));
// IDリストをえる
OleCheck(Desktop.ParseDisplayName(0, Nil, PWideChar(NameW), pchEaten, pIDList, Attributes));
if not SHGetPathFromIDList(pIDList, Buffer) then
raise EConvertError.Create('ファイルを変換できません。');
Result := StrPas(Buffer);
end;
WideStringを使うことを覗けば、IShellFolderのParseDisplayNameメソッドとSHGetPathFromIDList
を使うだけです。[Tips:233]よりすっきりしましたか。
※ 使用できるOS、バァージョンに注意して下さい。
参照: [Delphi-ML:7322] <その他Windows関連> <Windows> <PASCAL>
0099 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/08 osamu rev 1.2 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 2005/12/31 長山 編集
リンクファイルから参照先のファイル名を得る
IShellLinkを使用すれば出来ます。
CoInitialize(NULL);
HRESULT HR;
IShellLink *psl;
IPersistFile *ppf;
WideChar wsz[MAX_PATH];
char szGotPath[MAX_PATH];
WIN32_FIND_DATA wfd;
HR = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
if(SUCCEEDED(HR)){
HR = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
if(SUCCEEDED(HR)){
MultiByteToWideChar(CP_ACP, 0, "ショートカット.lnk", -1,
wsz, MAX_PATH );
HR = ppf->Load( wsz, STGM_READ );
if(SUCCEEDED(HR)){
HR = psl->Resolve(Application->Handle, SLR_ANY_MATCH);
if(SUCCEEDED(HR)){
HR = psl->GetPath(szGotPath, MAX_PATH,
(WIN32_FIND_DATA *)&wfd, SLGP_SHORTPATH );
Edit2->Text = szGotPath;
}
}
}
ppf->Release();
}
psl->Release();
}
CoUninitialize();
Delphi翻訳版 (関数です)
uses
Windows, SysUtils, ShlObj, ActiveX, ComObj;
const IID_IPersistFile: TGUID= (D1:$0000010B;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));
function ExtractStringFromLinkFile( Target:TFileName ): String;
var
R : HRESULT;
SL : IShellLink;
PF : IPersistFile;
Wrk : array[0..MAX_PATH] of WideChar;
Path: array[0..MAX_PATH] of Char;
WFD : WIN32_FIND_DATA;
begin
Result := '';
CoInitialize( NIL );
R := CoCreateInstance( CLSID_ShellLink, NIL, CLSCTX_INPROC_SERVER, IID_IShellLinkA, SL );
if Succeeded( R ) then
begin
R := SL.QueryInterface( IID_IPersistFile, PF );
if Succeeded( R ) then
begin
MultiByteToWideChar( CP_ACP, 0, PChar(Target), -1, Wrk, MAX_PATH );
R := PF.Load( Wrk, STGM_READ );
if Succeeded( R ) then
begin
R := SL.Resolve( 0{Application.Handle}, SLR_ANY_MATCH );
if Succeeded( R ) then
begin
SL.GetPath( Path, MAX_PATH, WFD, SLGP_SHORTPATH );
Result := Path;
end;
end;
end;
end;
CoUninitialize;
end;
参照: [builder:5475] <ShellApi> <Windows>
0173 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/03/08 osamu rev 1.2 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 2003/06/27 osamu 編集
ファイルの更新日時を得る
Windows 的な方法としては、FindFirst/FindClose を使って、得られた TSerchRec を読みます。
別解として、PASCAL の FileAge 関数を使った方法を、ひきさんが以下のホームページで解説してくださっています。
[Delphi壁の穴]-[その二:システムを覗く]
http://hp.vector.co.jp/authors/VA009712/take/delphi/kabesys.htm#datetimefile1
http://hp.vector.co.jp/authors/VA009712/take/delphi/kabesys.htm#datetimefile2
参照: <日時> <PASCAL>
0331 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 2003/06/25 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 2003/06/25 osamu 編集
FindFirst でアイコンを変更したディレクトリを検索できない
Delphi7, WinXPです。XPにはフォルダのアイコンイメージを変更することができるのですが、これを適用したフォルダをFindFirstは認識しません。
この投稿に簡単な解決法は投稿されませんでした。FindFirstFileEx API や Shell 関連の API を使うことで回避できるかもしれないとの意見がありました。
参照: [Delphi-ML:73372] <Windows>
0330 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 2003/06/25 osamu rev 1.2 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 2003/06/25 osamu 編集
FindFirst による4文字以上の拡張子の判別
Q.FindFirst,FindNextを使用してファイル名を取得しているのですが、PATH定数を "C:\TEST\*.jpg" と指定した場合、拡張子が「.jpg」のファイルだけでなく退避用にリネームした”XXXX.Jpg_”といったファイルまでヒットしてしまいます。
A.WinXPには4文字以上の拡張子を正しく認識させるためのレジストリが用意されています。以下の方法を試してみてはいかがでしょうか。Win2000でも同じことができるかどうかはわかりません。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem の Win95TruncatedExtensions を 0 にして再起動。
参照: [Delphi-ML:73374] <Windows>
0274 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/09/24 osamu rev 1.3 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 2001/05/14 jkaneko@fujita.co.jp 編集
ディレクトリのファイルを列挙する
以下のようにするのが定石です。
ポイントは,
2バイト文字の2バイト目に '\' が来る可能性を考慮する
-> IsPathDelimiter 関数
FindFirst が成功したときのみ FindClose を呼ぶ。
-> [Delphi-ML:17508]
repeat until を使うとループがスマートに書ける
'.' や '..' といった特殊ディレクトリも列挙される
といったところです。
SearchRec.FindData には見つかったファイルに関するさらに多くの情報が詰まっています。ヘルプを参照しましょう。
procedure Form1.EnumFiles(DirectoryName: string);
var
SearchRec: TSearchRec;
begin
// 一番後ろに '\' がついていなければ付ける
DirectoryName:= IncludeTrailingBackslash(DirectoryName);
// FindFirst が成功した場合のみ FindClose を呼ぶ必要がある
if 0=FindFirst(DirectoryName+'*.*', faAnyFile, SearchRec) then try
repeat
if SearchRec.Attr and faDirectory <> 0 then begin
// カレントディレクトリや親ディレクトリをスキップ
if (SearchRec.Name='.') and (SearchRec.Name='..') then
Continue;
// ディレクトリに対する処理
// SearchRec.Name にディレクトリ名が入っている
// たとえば、Memo1.Lines.Add('Dir :'+DirectoryName+SearchRec.Name);
end else begin
// ファイルに対する処理
// SearchRec.Name にファイル名が入っている
// たとえば、Memo1.Lines.Add('File:'+DirectoryName+SearchRec.Name);
end;
until 0<>FindNext(SearchRec);
finally
FindClose(SearchRec);
end;
end;
参照:
0233 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/09/03 西坂良幸 rev 1.6 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/09/27 西坂良幸 編集
短いファイル名を長いファイル名に変換したい。
長いファイル名を短いファイル名にするのは、APIにGetShortPathNameという関数があるで簡単ですが([Tips:68])、逆の長いファイル名にするのはちょっと工夫が必要です。
APIのFindFirstFile関数を使うとパラメータのWIN32_FIND_DATA構造体のcAlternateFileNameに短いファイル名あり、長いファイル名はcFileNameにあります。
したがって、長い→短い、短い→長いの変換は基本的には、ファイル名を使ってもう一度FindFirstしてやればいいわけです。
効率を無視すれば次のようものでしょうか。
この関数ではドライブレターの大文字小文字は変換されませんので、必要であれば後から大文字に変換してください。
function ShortToLongFileName(ShortName: String):String;
var
SearchRec: TSearchRec;
begin
result:= '';
// フルパス化
ShortName:= ExpandFileName(ShortName);
// 長い名前に変換(ディレクトリも)
while LastDelimiter('\', ShortName) >= 3 do begin
if FindFirst(ShortName, faAnyFile, SearchRec) = 0 then
try
result := '\' + SearchRec.Name + result;
finally
// 見つかったときだけ Close -> [Delphi-ML:17508] を参照
FindClose(SearchRec);
end
else
// ファイルが見つからなければそのまま
result := '\' + ExtractFileName(ShortName) + result;
ShortName := ExtractFilePath(ShortName);
SetLength(ShortName, Length(ShortName)-1); // 最後の '\' を削除
end;
result := ShortName + result;
end;
※ [Tips:273]に同様の結果を得るCOM版があります。
参照: [Delphi-ML:3333] [Delphi-ML:7320] [Delphi-ML:7322] [Delphi-ML:17508] [Tips:68] [Tips:273]
0218 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/08/26 西坂良幸 rev 1.2 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/09/27 西坂良幸 編集
エクスプローラからファイルをドラッグ&ドロップする
一度はやってみたいんですよね。MLでも多いスレッドです。
「Delphi2.0Q&A120選」(大野元久著)にもあります。
WM_DropFilesメッセージを捕まえて、DragQueryFile関数で処理するわけですが、受け取る側のスタイルを準備しなければなりません。
これは、一般的なフォームのOnCreateイベントで
DragAcceptFiles(Handle,True);
を使うよりも、CreateParamsをオーバーライドするのがベターだそうです。
// 定義部
type
TForm1 = class(TForm)
・・省略・・
private
procedure CreateParams(var Params: TCreateParams);override;
procedure WMDropFiles(Var Msg: TWMDropFiles); Message WM_DropFiles;
public
end;
// 実装部
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
// 受け取れる準備をする
Params.ExStyle := Params.EXStyle or WS_EX_ACCEPTFILES;
end;
// ファイル1個の場合−−メモに読み込ませる。
procedure TForm1.WMDropFiles(Var Msg: TWMDropFiles);
Var
FileName: Array[0..MAX_PATH] of Char;
Begin
Count := DragQueryFile(Msg.Drop, 0, FileName, SizeOf(FileName));
Memo1.Lines.LoadFromFile(String(FileName));
DragFinish(Msg.Drop);
End;
//今度は複数の場合−−リストボックスにファイル名
procedure TForm1.WMDropFiles(Var Msg: TWMDropFiles);
Var
FileName: Array[0..MAX_PATH] of Char;
i, Count: integer;
Begin
ListBox1.Items.clear;
// 第二パラメータを-1にするとドロップ数が取得できる
Count := DragQueryFile(Msg.Drop, DWord(-1), FileName, SizeOf(FileName));
for i := 0 to count - 1 do
begin
DragQueryFile(Msg.Drop, i, FileName, SizeOf(FileName));
ListBox1.items.add(String(FileName));
end;
DragFinish(Msg.Drop);
End;
最後のDragFinishを忘れないように。
参照: [Delphi-ML:3137] [Delphi-ML:8536] [Delphi-ML:31274] <ShellApi> <Windows>
0275 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/09/26 西坂良幸 rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/09/26 西坂良幸 編集
ファイルを削除してゴミ箱に移動させたい。
SHFileOperation関数を使えば、ファイル単位でもフォルダーごとでもゴミ箱に移動させることができます。
注意事項としては、必ずフルパスでなければならないということです。
ちょっと変な関数名ですが・・・
Uses Shellapi;
procedure SendToRecycleBin(FileList: TStrings; Dlg: boolean);
var
LpFileOp:TSHFILEOPSTRUCT;
FileNames: string;
i: integer;
begin
if FileList.Count = 0 then exit;
// #0をデリミタとした文字列を作る
for i := 0 to FileList.Count - 1 do
FileNames := FileNames + FileList[i] + #0;
// ターミネイタにもう一度#0をつける
FileNames := FileNames + #0;
with LpFileOp do
begin
Wnd := Application.Handle;
wFunc := FO_DELETE;
pFrom := PChar(FileNames);
pTo:= nil;
fFlags := FOF_ALLOWUNDO;
if not Dlg then fFlags := fFlags or FOF_SILENT;
hNameMappings := nil;
lpszProgressTitle := nil;
end;
SHFileOperation(LpFileOp);
end;
// テスト
procedure TForm1.Button1Click(Sender: TObject);
var
Flist :TStrings;
begin
Flist := TStringlist.Create;
try
Flist.Add('C:\Program Files\Borland\Delphi 4\Projects\*.~df');
Flist.Add('C:\Program Files\Borland\Delphi 4\Projects\*.~pa');
SendToRecycleBin(FList, true);
finally
Flist.free;
end;
end;
参照: [Delphi-ML:3443] [Delphi-ML:5005] <ShellApi> <Windows>
0196 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/07/07 osamu rev 1.3 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/09/24 K.Takaoka 編集
Windows 特殊フォルダの Class ID List
SHGetFolderPath, SHGetFolderLocation, SHGetSpecialFolderPath, SHGetSpecialFolderPath といった API で Windows が特別に扱うフォルダのパスを得ることができます.
これらのフォルダはユーザ環境によって異なるため, 常に API を利用して取得するようにすると問題のないアプリケーションが開発できます.
フォルダ名:CSIDL名(プログラムで利用できる定数名)
{CLSIDL}
ディレクトリ名
マイコンピュータ: CSIDL_DRIVES
{20D04FE0-3AEA-1069-A2D8-08002B30309D}
マイコンピュータはディレクトリにリンクしていません
ネットワークコンピュータ: CLSIDL_NETWORK, CSIDL_NETHOOD
{208D2C60-3AEA-1069-A2D7-08002B30309D}
ネットワークコンピュータはディレクトリにリンクしていません
マイドキュメント: CSIDL_PERSONAL
{450D8FBA-AD25-11D0-98A8-0800361B1103}
C:\My Document
C:\WinNT\Users\UserName\Personal
ごみ箱: CSIDL_BITBUCKET
{645FF040-5081-101B-9F08-00AA002F954E}
C:\Recycled.Bin
コントロールパネル: CSIDL_CONTROLS
{21EC2020-3AEA-1069-A2DD-08002B30309D}
コントロールパネルはディレクトリにリンクしていません
プリンタ: CSIDL_PRINTERS, CSIDL_PRINTHOOD
{2227A280-3AEA-1069-A2DE-08002B30309D}
プリンタフォルダはディレクトリにリンクしていません
他にも
CSIDL_COOKIES, CSIDL_DESKTOP, CSIDL_DESKTOPDIRECTORY, CSIDL_FAVORITES, CSIDL_FONTS, CSIDL_HISTORY, CSIDL_INTERNET, CSIDL_INTERNET_CACHE, CSIDL_PROGRAMS, CSIDL_RECENT, CSIDL_SENDTO, CSIDL_STARTMENU, CSIDL_STARTUP, CSIDL_TEMPLATES
などといったものが Win95/98/NT4/2K で共通に利用できます.
WinNT/2K においては CSIDL_COMMON_*** という形式で全ユーザ共通のフォルダを指定できるものが多くあり, Win2K にはさらに多くの定数が新設されています.
基本的には MSDN などの Microsoft の公式な文書を読むことになりますが, HKEY_CLASSES_ROOT\CLSID\ 以下を探すことで, アプリケーション固有のものを発見することができます.
たとえば、
「受信トレイ」
{00020D75-0000-0000-C000-000000000046}
といったものです.
これらを利用して 'プリンタ.{2227A280-3AEA-1069-A2DE-08002B30309D}' という名前のフォルダを作ることで、任意の場所にプリンタフォルダを追加できます。
参考: http://msdn.microsoft.com/library/sdkdoc/Shell/Functions/CSIDL.htm
参照: [Delphi-ML:10601] <Windows>
0068 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/08 osamu rev 1.2 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/09/22 osamu 編集
長いファイル名を短いファイル名に変換したい
GetShortPathName APIを使いましょう。
function LongToShortFileName(Const LongName: String):String;
var
Len: integer;
begin
Len := GetShortPathName(PChar(LongName), PChar(result), 0);
SetLength(result, len);
if GetShortPathName(PChar(LongName), PChar(result), Len) = 0 then
Raise EConvertError.Create('ファイルが見つかりません。');
end;
ファイルが実在しないと例外が発生します。
逆に、短いファイル名を長いファイル名にするには [Tips:233] を見てください。
参照: [builder:5092] [Tips:233] <Windows>
0240 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/09/08 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/09/08 osamu 編集
任意のドライブをセクタ単位で読み書きする
Q:
MS-DOS Ver.2.1でフォーマットされたFDをWin95で読込みたいのですが、どのようにすればよいのでしょうか?
セクタ単位で読込む方法が解りません。
A:
'\\.\A:' で該当のドライブ( A: の部分を適宜変更)に対して CreateFile() すればアクセスできます。
# You can use the CreateFile function to open a disk drive
# or a partition on a disk drive. The function returns a
# handle to the disk device; that handle can be used with
# the DeviceIOControl function. The following requirements
# must be met in order for such a call to succeed:
#
# The caller must have administrative privileges for the
# operation to succeed on a hard disk drive.
# The lpFileName string should be of the form \\.\PHYSICALDRIVEx
# to open the hard disk x. Hard disk numbers start
注意として GetDiskFreeSpace() でセクタサイズを調べて FILE_FLAG_NO_BUFFERING でアクセスしてください。
参照: [Delphi-ML:32482]
0143 D1 D2 D3 D4 D5 D6 D7 3.1 95 98作成: 1999/02/11 osamu rev 1.2 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/09/08 osamu 編集
フォルダのタイムスタンプを変更する
ファイルのタイムスタンプを変更するのはできるのですがフォルダのタイムスタンプはどのようにして変更したらよいのでしょうか?
procedure ChangeDirTime(DirName : String;Date : TDateTime);
var
FHandle : integer;
Begin
FHandle := CreateFile(Pchar(DirName), { ディレクトリ名最後に\はいらない }
GENERIC_WRITE, { 書きこみ許可しないと変えられない }
FILE_SHARE_Read, { 最低他からアクセスできないとハンドルがもらえない }
nil, { セキュリティは無視(いいのかな?) }
OPEN_EXISTING, { ディレクトリは存在していることを前提 }
FILE_FLAG_BACKUP_SEMANTICS, { APIのヘルプをみてね }
0);
FileSetDate(FHandle,DateTimeToFileDate(Date));
CloseHandle(FHandle);
End;
タイムスタンプの設定にAPIのSetFileTimeを使う手もありますがフォルダならこれで十分です。
D3+Win98 では動きませんでした。NT では動くのかな???
参照: [Delphi-ML:24889] <Windows>
0182 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/05/08 osamu rev 1.2 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/08/26 西坂良幸 編集
他のアプリの起動パスを取得する
> (ウィンドウハンドルの場合)
> GetWindowLong(hwnd, GWL_HINSTANCE) でモジュールハンドルを取り出す。
> (モジュールハンドルの場合)
> GetModuleFileName(hModule, strBuffer, nBufferSize) でファイル名を得る。
残念ですがこの方法では、他のアプリの起動パス は取得できません。自分自身のExe名しか取得できません。(私も最初はこれではまった。)(^.^)
モジュールハンドルはプロセス毎に独立して管理されるので、他のアプリ(他のプロセス)のモジュールハンドルを持ってきても意味がありません。
http://www.microsoft.com/japan/support/kb/articles/J041/6/32.htm
にシステム内で稼働中のプロセスを列挙する方法がでてますから、参考にしてください。ウィンドウハンドルが判っているのでしたら、
GetWindowthreadProcessID でプロセスIDを求めて、列挙中にこれと合致するプロセスを探せばよいでしょう。
たとえば、Win95/98用(WinNTではダメ)ですが、
uses TLHelp32;
// ハンドルからファイル名を得る
function GetProcesFileNameFrom(Handle: hWnd):string;
var
PID: DWORD;
SnapShot: THandle;
ProcessEntry32: TProcessEntry32;
begin
// ハンドルから作成スレッドを調べてプロセスIDを得る
GetWindowThreadProcessId(Handle, @PID);
// TProcessEntry32構造体の初期化
ProcessEntry32.dwSize := SizeOf(TProcessEntry32);
// システム中の情報のスナップショットをとる
SnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
try
// 最初のプロセスの検索
if Process32First(SnapShot, ProcessEntry32) then
begin
repeat
// IDが一致したら
if ProcessEntry32.th32ProcessID = PID then
begin
Result := string(ProcessEntry32.szExeFile);
break;
end;
// 次のプロセスの検索
until Process32Next(SnapShot, ProcessEntry32) = False;
end;
finally
CloseHandle(SnapShot);
end;
end;
などです。
参照: [Delphi-ML:30032] <アプリケーション> <Windows>
0163 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/11 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/11 osamu 編集
カレントユーザのデスクトップディレクトリを得る
>実行中に現在の(ユーザの)「デスクトップ」ディレクトリのパスを取得したい
>のですが、どうすれば良いのでしょうか?
こんなの有ります。
uses ShellAPI, SHlObj, ComObj, ActiveX;
:
:
function GetDesktopFolder: string;
function GetDispName(shi: IShellFolder; pidl: PItemIDList): string;
var DispName: TStrRet;
begin
shi.GetDisplayNameOf(pidl, SHGDN_FORPARSING, DispName);
if DispName.uType = STRRET_CSTR then
Result := DispName.cStr
else if DispName.uType = STRRET_OFFSET then
Result := PCHAR(LongInt(pidl) + DispName.uOffset)
else
Result := WideCharToString(DispName.pOleStr);
end;
var Pidl: PItemIDList;
DesktopFolderI: IShellFolder;
begin
OleCheck(SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, Pidl));
try
OleCheck(SHGetDesktopFolder(DesktopFolderI));
Result := GetDispName(DesktopFolderI, Pidl);
finally
CoTaskMemFree(Pidl);
end;
end;
参照: [Delphi-ML:31606] <Windows>
0161 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/11 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/11 osamu 編集
TFileStream で標準出力に表示
> テキストファイルの入出力は TStringList でやると便利です。
> そこで、コンソールアプリケーションの標準出力でも使いたいなと、
> SaveToFile('con') を実行したところ例外で失敗しました。
> VCLソースを追いかけてみたところ、TFileStream.Create() で例外が起きていました。
>
> ところが、SaveToFile('nul') を実行したところ、なにも出力されないとはいえ
> 例外が発生することなく実行できました。
>
> 簡単に使えないのはしかたないのですが、この違いはなんでしょうね?
これ、'con'の代わりに'conout$'だと行けるみたいですね。
ところで、ちょっと横道にそれますけど、'con'だと仮にopen出来ても
リダイレクトした場合にまでコンソールに表示されて場合によっては
不便じゃありませんか?
その場合は以下のようにした方が良いかと。
uses
windows, classes, sysutils;
var
s : TStringList;
hs : THandleStream;
begin
s := TStringList.Create;
try
hs := THandleStream.Create(GetStdHandle(STD_OUTPUT_HANDLE));
try
s.SetText('一行目'#10'二行目'#10'三行目'#10);
s.SaveToStream(hs);
finally
hs.free;
end;
finally
s.free;
end;
end.
参照: [Delphi-ML:31323] <Windows>
0153 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/11 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/11 osamu 編集
エクスプローラで使われるアイコンを取得・変更する
> Windowsでディレクトリなどに使われるアイコンを変更するなどの
> プログラムもあるみたいですが、そういったシステムで使われる
> アイコンを取得したいと思っています。
レジストリの HKEY_LOCAL_MACHINE の下に
Software\Microsoft\Windows\CurrentVersion\explorer\Shell Icons
というキーがあり、ここに番号の文字列を作り、アイコンのファイル名とインデックスを設定することによりアイコンが設定可能です。
参照: [Delphi-ML:26403] <Windows> <アイコン>
0147 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/11 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/11 osamu 編集
クリップボードにコピーされたファイル・ディレクトリ
> クリップボードからペーストなのですが、どのようにしたらファイル名
> なのか確認できますか?その取り出し方も教えていただけないでしょうか?
プログラム上、考慮することが2点(だけかな?)、あります。
1) Explorer上で「コピー」した場合は、クリップボード内にCF_HDROPフォーマットのデータが入るようになってます。この場合、ファイルの有無はこのフォーマットの有無で判断できます。例は下のほうに置いておきます。
2) IE4が出てから、Explorerに「アドレス」なるコンボボックスが付きやがりまして、ここでディレクトリ名の「コピー」、できちまうんスよ、ったく。こいつ、テキスト形式(CF_TEXT)なんでね、これも考慮するとくりゃ、テキストがファイル名として正しいのか、白黒つけなきゃならないんスね。あ〜こりゃこりゃ。ちと面倒なコトをするハメになりそうっスよ、ったく。くぁ〜、まぃったねぇ。あっしぁ、面倒みきれませんぜ。なんせ あっし、ほれ、バカなんで。
// uses Clipbrd, ShellAPI;
procedure TForm1.Button1Click(Sender: TObject);
var
i,
n: integer;
hDrop: THandle;
szFile: array[0..MAX_PATH-1] of Char;
begin
if HasFormat(CF_HDROP) then
begin
hDrop := GetAsHandle(CF_HDROP);
n := DragQueryFile(hDrop, $FFFFFFFF, szFile, MAX_PATH); // -1かな?(64bit用)
Caption := Format('FileCount : %d', [n]);
for i := 0 to n - 1 do
begin
DragQueryFile(hDrop, i, szFile, MAX_PATH);
ListBox1.Items.Add(szFile);
end;
end;
end;
参照: [Delphi-ML:25073] <その他Windows関連> <Windows>
0140 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/11 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/11 osamu 編集
リムーバブルドライブの種類を判別する
結局結論は出たのでしょうか???
参照: [Delphi-ML:24577] <Windows>
0133 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/08 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/08 osamu 編集
リードオンリーファイルを Assign/Reset で読もうとするとエラーになる
Reset する前に FileMode 変数をセットしましょう。
参照: [Delphi-ML:23966]
0061 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/08 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/08 osamu 編集
複数プログラムから同一内容のメモリを参照/更新する
Win32用に、中村@NECさんが、File Mapping を利用して実現したクラスを [Delphi-ML:19603] で紹介されています。
ただ、添付ファイルは Web からは取れません。
どこか他からダウンロードしないと。。。
参照: [Delphi-ML:19603] <Windows> <メモリ>
0070 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/08 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/08 osamu 編集
OpenDialogでたくさんファイルを選択するとエラー
ファイル名を保存するバッファが 8KB 固定のために起こります。
VCL に手を入れるか、自分で GetOpenFileName API を呼ぶしか回避できません。
参照: [builder:5117] <バグ> <ダイアログ>
0017 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/08 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/08 osamu 編集
TDriveComboBoxの内容の更新
ネットワークドライブの割当てをした後、TDriveComboBoxにて割当てたドライブを反映させたいのですが、方法が解りません。
DriveComboBox1.TextCase:=DriveComboBox1.TextCase;
たぶんこれが一番楽な方法だと思います。
非常に裏わざ臭いですが。。。
参照: [Delphi-ML:7162] <System> <バグ> <コンポーネント >
0002 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/02/08 osamu rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/02/08 osamu 編集
NTで他のアプリが開いているファイルを知る
WindowsNT上ならば、
http://www.ntinternals.com/
に NTFilemon があります。
ソースが公開されているので、参考になるかもしれません。
参照: [Delphi-ML:18558] <Windows>
[新規作成] [最新の情報に更新]
How To
Lounge
KeyWords
Osamu Takeuchi osamu@big.or.jp
Tips
Delphi
Home