旧Delphi FAQ - Windows API

Abstract: このQ&Aは、旧www.borland.co.jp に掲載されていた記事を転載したものです。記事は掲載時点の情報をあるがままに掲載しており、新バージョンでのご利用においては、コンポーネントやAPIの仕様変更等によりご利用いただけない場合がありますのでご留意ください

    EXE ファイルを起動する方法

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
EXE ファイルを起動しても,その起動した処理の終了を待たずにすぐリターンする関数を教えてください。

A:
WinExec を使用してください。 WinExec は Windows API でアプリケーションの起動後,即座(呼び出されたアプリケーションが終了していなくとも)に呼び出しアプリケーションに制御を戻します。

    アプリケーションの二重起動を抑止する

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
アプリケーションの二重起動を抑止するにはどうしたらよいのでしょうか?

A:
Version 1.0J では:
hPrevInst という標準変数が 0 でなければそのプログラムはすでに起動されています。アプリケーションの起動時にこのデータをチェックするようにしてください。

if hPrevInst <> 0 then Exit; 

A:
Version2.0J以降では:
アプリケーション固有のミューテックスオブジェクトを作成し,そのミューテックスオブジェクトが存在するかしないかで,アプリケーションを実行または中止することができます。
以下のコードをお試しください。
このコードは,[表示(V)|プロジェクト ソース(J)] で表示されるプロジェクトソースに記述してください。

   program Mutex;
   
   uses
     Forms,
     Windows,
     Mutex1 in 'Mutex1.pas' {Form1};
   
   {$R *.RES}
   
   const
     MutexName = 'EX_Mutex';
   var
     hMutex: THANDLE;
   begin
     hMutex := OpenMutex(MUTEX_ALL_ACCESS, False, MutexName);
     if hMutex <> 0 then
     begin
       CloseHandle(hMutex);
       Exit;
     end;
     hMutex := CreateMutex(nil, False, MutexName);
     Application.Initialize;
     Application.CreateForm(TForm1, Form1);
     Application.Run;
     ReleaseMutex(hMutex);
   end.

    WritePrivateProfileString 関数について

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
フォームの色を WinAPI の WritePrivateProfileString 関数を使って INIファイルに保存しようとしましたが,うまくいきません。

    rc := WritePrivateProfileString( 'Test', 'Formcolor',
          IntToStr( ColorToRGB( Form1.Color ) ), 'c:\test.ini');

と書きましたが,「type mismatch」のエラーが発生します。フォームの色に限らず,例えば WindowStyleを.INI ファイルに保存したいと思ったら,どうしたらよいのでしょうか。

A:
通常,Pascal では1バイトの文字数領域と文字列の組み合わせからなるstring 型で文字列を表現しますが,Windows ではヌルターミネータ(文字コード0)をつけた文字列を表現します。 これを Delphi ではPChar であらわします。 これらの型を相互に変換するために StrPas や StrPCopy などの関数があります。
そして,Windows API(ここでは WritePrivateProfileString)は文字列を PChar で受け取るのに対し,IntToStr は string で返すために,型が一致していないわけです。 いったん,char 配列を用意して,IntToStr の結果をStrPCopy で転送してから WritePrivateProfileString に渡せばコンパイルできるようになるでしょう。 なお,INI ファイルに対する処理は次のように TIniFile オブジェクトを使用すると便利です。

    var
      ini: TIniFile;
    begin
      try
        ini := TIniFile.Create( 'TEST.INI' );
        ini.WriteString( 'TEST', 'Formcolor',
        IntToStr( ColorToRGB( Form1.Color ) ) );
      finally
        ini.Free;
      end;
    end;

    TForm の Window Handle

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
ウィンドウハンドルが必要な Windosw API を呼び出すにはどうしますか?

A:
ウィンドウハンドルが必要な Windosw API を呼び出す場合は TForm の Handle プロパティを使用します。

ShowWindow(Form2.Handle, SW_SHOWMINNOACTIVE); 

    Form や Image の HDC(デバイスコンテキスト)の指定方法

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Form や Image の HDC(デバイスコンテキスト)の指定方法を教えて下さい。
WinAPI の BitBlt 関数を使用したいのですが。

A:
DC に対するハンドルはたとえば,PaintBox1.Canvas.Handle で,HDC が取得できます。 TCanvas の HELP で関連情報が関連情報を確認できます。

スクリーンの HDC は GetDC(0) でとれます。 たとえば,フォームにPaintBox1 を張り付けて

BitBlt(PaintBox1.Canvas.Handle,0,0,200,100,GetDC(0),0,0,SRCCOPY); 

を指定すると,左上の隅から 200×100 がコピーされます。

    ミリセカンド(1/100 秒)の取得

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
現在の時刻として,ミリセカンド(1/100 秒)を取得する方法はありませんか?
ある処理の実行時間を「終了時の時刻 - 起動時の時刻」で算出したい。

A:
ある処理の起動時に,GetTickCount を取得しておき,終了時にも GetTickCount を取得し,その差を表示します。 GetTickCountは,ミリ秒単位なので実行時間の表示形式を変換する必要があります。

   var
     Form1: TForm1;
     win_create,win_close : LongInt;
   
   implementation
   
   {$R *.DFM}
   
   procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
   begin
     win_close := GetTickCount;
     label2.Caption :=  '終了 : ' + TimeToStr(Time);
     label3.Caption :='実行時間は '+inttostr(win_close - win_create)+' ミリ秒';
     if MessageDlg('実行時間', mtConfirmation, [mbOk, mbCancel], 0) = mrCancel
       then
         CanClose := False;
   end;
   
   procedure TForm1.FormCreate(Sender: TObject);
   begin
        win_create := GetTickCount;
        label1.Caption :=  '開始 : ' + TimeToStr(Time);
   end;

    CopyLZFile の使い方

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Windows の API の CopyLZFile を Delphi で使うにはどうすればよいでしょうか?

A:
次のように行えます。

   type
      farr = Array[0..3] of PChar;
   var
      hfSrcFile,
      hfDstFile: Integer ;
      ofStrSrc,
      ofStrDst: TOFSTRUCT ;
      I: Integer ;
   Const
      szSrc: farr = ('c:\temp\1.txt', 'c:\temp\2.txt',
                     'c:\temp\3.txt', 'c:\temp\4.txt') ;
      szDst: farr = ('c:\temp\1.bak', 'c:\temp\2.bak',
                     'c:\temp\3.bak', 'c:\temp\4.bak') ;
   begin
      LZStart;
      for I:=0 to 3 do
      begin
          hfSrcFile := LZOpenFile(szSrc[I], ofStrSrc, OF_READ) ;
          hfDstFile := LZOpenFile(szDst[I], ofStrDst, OF_CREATE) ;
          CopyLZFile(hfSrcFile, hfDstFile) ;
          LZClose(hfSrcFile) ;
          LZClose(hfDstFile) ;
      end ;
      LZDone ;

    フロッピーディスクをフォーマットしたいのですが?

該当するバージョン:Delphi 1.0

Q:
フロッピーディスクをフォーマットしたいのですが,どうしたら良いですか?

A:
コマンドラインツール FORMAT.EXE によりフォーマットすることができます。
使い方は,下記コードを参考にして下さい。

   WinExec('dosprmpt.pif /c c:\dos\format a: < c:\windows\temp\format.tmp' ,SW_HIDE);

    コンソールアプリケーションで標準エラーに出力する

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Delphi では C/C++ で予め定義されたストリーム stderr がありません。
Write 手続きは標準出力へ,Read 手続きは標準入力に結び付けられています。

Windows API GetStdHandle を使用して標準エラーのハンドルを取得します。
コンソールアプリケーションで標準エラーに出力する簡単な例です。

   uses
     Windows, SysUtils;
   var
     stderr: TextFile;
     handle: Integer;
   begin
     AssignFile( stderr, 'CONOUT$' );
     ReWrite( stderr );
     handle : = TTextRec( stderr ).Handle;
     TTextRec( stderr ).Handle := Integer( GetStdHandle( STD_ERROR_HANDLE ) );
     WriteLn( 'stdout' );
     WriteLn( stderr, 'stderr' );
     TTextRec( stderr ).Handle := handle;
     CloseFile( stderr );
   end.

    メタファイルを TImage に表示させたいのですが?

該当するバージョン:Delphi2.0

Q:
メタファイルを TImage に表示させたいのですが,WMF(.WMF)形式のものはうまく表示することができません。どのようにすればよいのでしょうか?

A:
メタファイルには,EMF (Win32 Enhanced Metafile) 形式のものと WMF (Windows 3.1 Metafile, Aldus ヘッダー付き)形式のものがありますが, 32ビットで扱う場合は,EMF 形式に変換します。
下記コードはファイルを WMF から EMF に変換する例です。

   var
     MetaFile: TMetaFile;
   begin
     MetaFile := TMetaFile.Create;
     MetaFile.LoadFromFile(XXX.WMF');
     MetaFile.Enhanced := True;
     MetaFile.SaveToFile(XXX.EMF);
     MetaFile.Free;
   end;

    IME プロパティのないコンポーネントで IME 操作を行いたいのですが?

該当するバージョン:Delphi2.0

Q:
TStringGrid でセルがクリックされたことで IME を起動させ日本語入力を行いたいのですが,どのようにすればよいのでしょうか?

A:
下記例を参考にして下さい。

   uses IMECtrl;

   procedure TForm1.StringGrid1DrawCell(Sender: TObject; Col, Row: Longint;
     Rect: TRect; State: TGridDrawState);
   begin
     SetImeStatus(Form1.Handle, imHira);
   end;

    NotePad.exe を起動後,検索ボックスを表示するには

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Delphi 2.0 から Notepad.exe を起動後,Notepad の検索ボックスを表示するにはどうしますか?

A:
以下のように,メニューにメッセージを送ることで可能となります。

procedure TForm1.Button1Click(Sender: TObject);
var
  StartupInfo : TStartupInfo;
  ProcessInfo : TProcessInformation;
begin
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  CreateProcess(nil, 'c:\windows\Notepad.exe c:\program Files\Borland\delphi 2.0\Readme.txt',
                nil, nil,False, NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo,ProcessInfo)
end;

procedure TForm1.Button2Click(Sender: TObject);
const
  dest ='Readme.txt - メモ帳';
var
  Stat: Word;
  wnd: HWND;
  menu,
  smenu: HMENU;
  menuid: Word;
  capt: array[0..255] of char;
begin
  wnd := GetWindow(GetDesktopWindow, GW_Child);
  while wnd > 0 do begin
    if IsWindowVisible(wnd) then begin
      if GetWindowText(wnd, capt, sizeof(capt)) > 0 then begin
        if StrComp(dest, capt) = 0 then begin
          { menuid を取得}
          menu := GetMenu(wnd);
          smenu := GetSubMenu(menu, 2); {検索 - 第2引数は,
                                           メニューの順番,最初は0}
          menuid := GetMenuItemID(smenu, 0); {文字列の検索 - 第2引数は,
                                               メニューの順番,最初は0}
          SendMessage(wnd,WM_COMMAND,menuid, 1);
          break;
      end;
    end;
  end;
    wnd := GetWindow(wnd, GW_HWNDNEXT);
  end;
end;

    マウスポインタを任意の位置に移動させるには,どうしますか?

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
マウスポインタを任意の位置に移動させるには,どうしますか?

A:
WinAPI の SetCursorPos() を使用することでマウスポインタを移動できます。
次のコードは,Button2 をクリックすると,Button1 の中央にマウスポインタを移動します。

   procedure TForm1.Button3Click(Sender: TObject);
   var
     Q: TPoint;
   begin
     Q := Point(Button1.Width div 2, Button1.Height div 2);
     Q := Button1.ClientToScreen(Q);
     SetCursorPos(Q.X, Q.Y);
  end;

    リソースファイルから,ビットマップをロードするにはどうしますか?

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
リソースファイルから,ビットマップをロードするにはどうしますか?

A:
EXE ファイルにバインドされているリソース( MyBitmap.res )からビットマップリソースとパレット情報をロードします。

   implementation

   {$R *.DFM}
   {$R MyBitmap.res}

   procedure TForm1.Button1Click(Sender: TObject);
   begin
     { hInstance は,アプリケーションのインスタンス }}
     Image1.Picture.Bitmap.LoadFromResourceName(hInstance, 'BITMAP1');
     BitBtn1.Caption := '';
     BitBtn1.Glyph.LoadFromResourceName(hInstance, 'BITMAP2');
   end;

    ユーザー定義のメッセージを作成するにはどうしますか?

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
ユーザー定義のメッセージを作成するにはどうしますか?

A:
ユーザー定義メッセージの定義を行い,SendMessage() を使用して Form1.Handle に wm_MyMessage を送ります。
定数 WM_USER は,ユーザー定義メッセージの開始番号を表しています。
メッセージ識別子を定義する場合は,WM_USER 以上の番号を使用します。
メッセージとは,イベントに対して Windows が 生成するものです。

   const
     wm_MyMessage = wm_User + 10;
   
   type
     TForm1 = class(TForm)
       Button1: TButton;
       Label1: TLabel;
       procedure Button1Click(Sender: TObject);
     private
       { Private 宣言 }
       procedure MyMes( var mes: TMessage ); message wm_MyMessage;
     public
       { Public 宣言 }
     end;
   
   var
     Form1: TForm1;
   
   implementation
   
   {$R *.DFM}
   
   procedure TForm1.MyMes( var mes: TMessage );
   begin
     Label1.Caption := 'メッセージ感知';
   end;
   
   procedure TForm1.Button1Click(Sender: TObject);
   begin
     SendMessage( Form1.Handle, wm_MyMessage, 0, 0 );
   end;

    ファイルの日付と時間を取得するには,どうしたら良いですか?

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
ファイルの日付と時間を取得するには,どのようにしますか?

A:
FileGetDate 関数を使用して,ファイルの DOS のタイムスタンプを取得した後に,FileDateToDateTime 関数を使用して,TDateTime 型の値に変換します。その後,時刻形式の値を文字列に変換します。

TOpenDialog コンポーネントを使用して,ファイルを選択しています。

   function GetFileDate(TheFileName: string): string;
   var
     FHandle: integer;
   begin
     FHandle := FileOpen(TheFileName, 0);
     try
       Result := DateTimeToStr(FileDateToDateTime(FileGetDate(FHandle)));
     finally
       FileClose(FHandle);
     end;
   end;

   procedure TForm1.Button1Click(Sender: TObject);
   begin
      OpenDialog1.Execute;
      Edit1.Text := GetFileDate(OpenDialog1.FileName);
   end;

    ドライブの準備ができているかのチェックを行なうには,どうしたら良いですか?

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
ドライブの準備ができているかのチェックを行なうには,どうしたら良いですか? もし,ドライブの準備ができていない場合には,プログラムで用意したメッセージを表示するにはどうしたら良いですか?

A:
以下の関数は,引数としてドライブの文字を受け取り,ドライブにディスクが入っていると Ture を返し,入っていないと False を返します。

   function DiskInDrive(Drive: Char): Boolean;
   var
     ErrorMode: word;
   begin
     { 大文字へ変更 }
     if Drive in ['a'..'z'] then Dec(Drive, $20);
     { ['A'..'Z'] の文字であることを確認 }
     if not (Drive in ['A'..'Z']) then
       raise EConvertError.Create('無効なドライブ');
     { クリティカルエラーをオフにする }
     ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
     try
       { ドライブ 1 = a, 2 = b, 3 = c, 以下同様 }
       if DiskSize(Ord(Drive) - $40) = -1 then
         Result := False
       else
         Result := True;
     finally
       { error mode を復元 }
       SetErrorMode(ErrorMode);
     end;
   end;

   procedure TForm1.Button1Click(Sender: TObject);
   begin
     { ['a'..'z'] の文字を指定 }
     if not DiskInDrive(PChar(Edit1.Text)^) then
           MessageDlg(UpperCase(Edit1.Text) + 'ドライブの準備ができていません',
         mtInformation, [mbOk], 0);
   end;

    どのような種類のドライブが使用されているか確認したいのですが。

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
どのような種類のドライブが使用されているか,どのように確認しますか?

A:
GetDriveType (WinAPI) の引数に,確認したいドライブのルートのパスを指定すると,ドライブの種類が返されます。

unit DriveTyp;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function ShowDriveType(DriveLetter: char): string;
var
 i: word;

begin
  if DriveLetter in ['A'..'Z'] then {Make it lower case.}
    DriveLetter := chr(ord(DriveLetter) + $20);
  i := GetDriveType(PChar(DriveLetter + ':\'));
  case i of
    DRIVE_REMOVABLE: result := 'floppy';
    DRIVE_FIXED: result := 'hard disk';
    DRIVE_REMOTE: result := 'network drive';
    DRIVE_CDROM: result := 'CD_ROM';
    DRIVE_RAMDISK: result := 'RAMDISK';         
    else result := 'does not exist';
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit1.Text := ShowDriveType(PChar(Edit1.text)^);
end;

end.

    フォームのサイズを変更できないようにするにはどうしますか?

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
フォームのサイズを変更できないようにするにはどうしますか?

A:
以下の例は,Windows のメッセージである WM_GetMinMaxInfo を処理して,実行時にサイズを指定します。
この場合,フォームの「元のサイズに戻す(R)」は淡色表示となります。

unit minmax;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
  private
    { Private 宣言 }
    procedure WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo);
              message WM_GETMINMAXINFO;
    procedure WMInitMenuPopup(var Msg: TWMInitMenuPopup);
              message WM_INITMENUPOPUP;
    procedure WMNCHitTest(var Msg: TWMNCHitTest);
              message WM_NCHitTest;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

 procedure TForm1.WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo);
 begin
   inherited;
   with Msg.MinMaxInfo^ do
   begin
     ptMinTrackSize.x:= form1.width;
     ptMaxTrackSize.x:= form1.width;
     ptMinTrackSize.y:= form1.height;
     ptMaxTrackSize.y:= form1.height;
   end;
 end;

 procedure TForm1.WMInitMenuPopup(var Msg: TWMInitMenuPopup);
 begin
   inherited;
   if Msg.SystemMenu then
     EnableMenuItem(Msg.MenuPopup, SC_SIZE, MF_BYCOMMAND or MF_GRAYED)
 end;

 procedure TForm1.WMNCHitTest(var Msg: TWMNCHitTest);
 begin
   inherited;
   with Msg do
     if Result in [HTLEFT, HTRIGHT, HTBOTTOM, HTBOTTOMRIGHT,
                   HTBOTTOMLEFT, HTTOP, HTTOPRIGHT, HTTOPLEFT] then
       Result:= HTNOWHERE
 end;
 
end.

WM_GETMINMAXINFO メッセージのメッセージハンドラは,ウィンドウの最小と最大のトラックサイズを,設計時のフォームの Width と Height と同じに設定します。これだけで,フォームのサイズ変更を抑制するには十分ですが,この例では,他の2つのメッセージも処理して見かけを良くしています。

WM_INITMENUPOPUP メッセージは,フォームのシステムメニューの「サイズ変更(S)」オプションを淡色表示にします。これにより,この機能は使用できないということを示唆してします。

WM_NCHitTest メッセージは,フォームの境界にマウスカーソルが移動した際に,カーソルの形状が変化することを抑制します。これにより,フォームのサイズは変更できないということを示唆してします。

    TMemo コンポーネントの Lines プロパティを Windows API で使いたい

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
TMemo コンポーネントの Lines プロパティを Windows API で使いたいのですが,型が違うというエラーになってしまいます。どうすればよいでしょうか。

A:
TMemo コンポーネントの Lines プロパティやリストボックスの Items プロパティなどの文字列リスト(TStrings)では,GetText というメソッドを使ってヌルで終わる形式の文字列バッファのアドレスを取得できます。たとえば,フォームにTPaintBox と TMemo コンポーネントを配置し,Memo1 コンポーネントのテキストの内容を Windows API を使って PaintBox1 に描画するには,次のようにします。

   DrawText(PaintBox1.Canvas.Handle, Memo1.Lines.GetText, -1,
            PaintBox1.Canvas.ClipRect, DT_LEFT);

    FindFirst と the WIN_32_FIND_DATA 構造体の使用

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

FindFirst と the WIN_32_FIND_DATA 構造体の使用

FindFirst(),FindNext(),FindClose() 関数を使用して TSearchRec のWIN32_FIND_DATA構造体へのアクセス方法を説明します。

以下の例では,検索されたファイルのロングネームとショートネームを表示する方法を示します。
このコードは,WinAPI 関数への Delphi のラッパー関数として実現されています。

    var
    sr : TSearchRec;
    R : integer;
    begin
        R := Sysutils.FindFirst('C:\*.*', faAnyFile, sr);
        while R = 0 do
        begin
          Memo1.Lines.Add(sr.FindData.cFileName);
          if sr.FindData.cAlternateFileName <> '' then
            Memo1.Lines.Add(sr.FindData.cAlternateFileName)
          else
            Memo1.Lines.Add(sr.FindData.cFileName);
          R := Sysutils.FindNext(sr);
        end;
        Sysutils.FindClose(sr);
    end;

    ファイルのアイコンを取得する方法

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
特定のファイルを指定して,そのファイルのアイコンを取得するにはどのようにすればよいでしょうか。

A:
アイコンの取得は WindowsAPI 関数 ExtractIcon を使用します。
以下のコードはエクスプローラのアイコンを取得して Image コンポーネントに表示するサンプルです。ExctractIcon 関数は ShellAPI ユニットで定義されているので,uses 節に ShellAPI を追加しておきます。

var
   HI: HICON;
   IconIndex: Integer;
begin
  IconIndex := 0; { 登録されているアイコンのインデックスを指定 }
  HI := ExtractIcon( HInstance, 'C:\winnt\Explorer.exe', IconIndex );
  Image1.Picture.Icon.Handle := HI;
end;

    ネットワークドライブをマップするには

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Windows NT または Windows 95 を使用してネットワークドライブをマップするにはどうしますか?

A:
Windows API の WNetAddConnection2 を使用します。Windows.pas で定義された API 呼び出しのプロトタイプは以下のとおりです。

   function WNetAddConnection2W(var lpNetResource: TNetResourceW;
    lpPassword, lpUserName: PWideChar;
    dwFlags: DWORD): DWORD; stdcall;

この API を使用するには,以下に示すように lpNetResource に最低必要な引数を設定します。 この構造体を最初の引数とし,パスワード,ユーザー名,マシンにログオンする際にマップを実施するかどうかを決めるフラグを指定します。
以下のコードでは,パスワードダイアログボックスを表示して入力されたパスワードを WNetAddConnection2 の2番目の引数に渡します。

implementation

uses Psword;         { PasswordDlg のユニット }

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  NRW: TNetResource;
begin
  PasswordDlg.ShowModal;   { パスワードダイアログの表示 }
  with NRW do
  begin
    dwType := RESOURCETYPE_ANY;
    lpLocalName := 'K:';   { このドライブにマップされます。}
    lpRemoteName :=  '\\MyServer\MyDirectory'; { 共有ディレクトリの UNC }
    lpProvider := nil;
  end;
  if WNetAddConnection2(NRW,
                         PChar(PasswordDlg.Password.Text), { パスワード }
                        'MyUserName',                      { ユーザー名 }
                         CONNECT_UPDATE_PROFILE)  = NO_ERROR then
     MessageDlg('マップ成功', mtInformation, [mbOk], 0);
end;

    Windows の起動ディレクトリを取得する方法

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Windows の起動ディレクトリを取得する方法

A:
Windows の起動ディレクトリは,GetWindowsDirectory という API で取得することができます。下記の例では,取得したパス情報を Label に表示します。

procedure TForm1.Button1Click(Sender: TObject);
var
  PBuf :PChar;
begin
  GetMem(PBuf, 256);
  GetWindowsDirectory(PBuf, 256);
  Label1.caption := StrPas(PBuf);
  FreeMem(PBuf);
end;

    デスクトップまたはスタートメニューにショートカットを追加

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Windows 95/Windows NT4.0 のデスクトップまたはスタートメニューにショートカットを追加

このサンプルプロジェクトは,Windows 95 または Windows NT 4.0 のデスクトップまたはスタートメニューにショートカットを追加する簡単な方法を提示します。

新規プロジェクトを作成し,フォームに TButton を配置します。
(この TButton の Name プロパティは Button1 とします。)

このプログラムは,デスクトップ(コードを参照)またはスタートメニューにショートカットを追加します。作成されるショートカットは FooBar です。
これを実行すると,メモ帳が起動されて Autoexec.bat ファイルを開きます。

HKEY_CURRENT_USER レジストリキーの Desktop と Start Menu から値のデータを取得します。

参照するレジストリキーと値 HKEY_CURRENT_USER\Software\MicroSoft\Windows\CurrentVersion\Explorer\Shell Folders

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses
  ShlObj, ActiveX, ComObj, Registry;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyObject  : IUnknown;
  MySLink   : IShellLink;
  MyPFile   : IPersistFile;
  FileName  : String;
  Directory : String;
  WFileName : WideString;
  MyReg     : TRegIniFile;
begin
  MyObject := CreateComObject(CLSID_ShellLink);
  MySLink := MyObject as IShellLink;
  MyPFile := MyObject as IPersistFile;
  FileName := 'NOTEPAD.EXE';
  with MySLink do begin
    SetArguments('C:\AUTOEXEC.BAT');
    SetPath(PChar(FileName));
    SetWorkingDirectory(PChar(ExtractFilePath(FileName)));
  end;
  MyReg := TRegIniFile.Create(
    'Software\MicroSoft\Windows\CurrentVersion\Explorer');

// デスクトップにショートカットを追加します。
  Directory := MyReg.ReadString('Shell Folders','Desktop','');

// 以下の3行は,スタートメニューにショートカットを追加します。
//  Directory := MyReg.ReadString('Shell Folders','Start Menu','')+
//      '\Whoa!';
//  CreateDir(Directory);

  WFileName := Directory+'\FooBar.lnk';
  MyPFile.Save(PWChar(WFileName),False);
  MyReg.Free;
end;

end.

    他に動いているアプリケーションの一覧を知るには?

該当するバージョン:Delphi 1.0,Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
実行中のアプリケーションの一覧を取得するにはどうしたらよいのでしょう?

A:
Windows API の ToolHelp32ライブラリ内の関数を利用します。
Delphiではこのライブラリを TLHELP32.PAS で定義しております。
まず、TLHELP32.PASで定義されている CreateToolHelp32SbapShot 関数を用いて、その時点での Windows Handle の情報を固定します。
その後に, Process32First,Process32Next 関数を用いて一つずつ取得していきます。

なお、ToolHelp32ライブラリは、Windows 95、Windows 98、Windows ME、Windows 2000、および Windows XPの場合のみ使用できます。
Windows NTでは使用できませんのでご注意下さい。

以下の例では、取得したアプリケーションの一覧を TMemoコントロール上に表示します。
※ usesに TLHELP32を追加してください。

procedure TForm1.Button1Click(Sender: TObject);
var
  HList: TStringList;
begin
  HList := TStringList.Create;
  GetProcessesList(HList);
  Memo1.Lines := HList;
end;

procedure TForm1.GetProcessesList(List: TStringList);
var
  ListHandle: THandle;
  Pr: TProcessEntry32;
  Flag: Boolean;
begin
  ListHandle := CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 );
  if ListHandle <> -1 then
  begin
    try { of finally}
      List.Clear;
   Pr.dwSize := sizeof (PROCESSENTRY32);
      Flag := Process32First( ListHandle, Pr);
      repeat
        List.Add( StrPas( Pr.szExeFile) );
        Flag := Process32Next( ListHandle, Pr );
      until not Flag;
    finally
      CloseHandle( ListHandle );
    end; { of finally }
  end
  else
    ShowMessage('NoGetHandle');
end;

    デフォルトユーザー名またはネットワークに接続したユーザー名の取得 (1998/09/04)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
デフォルトユーザー名またはネットワークに接続したユーザー名の取得を行うにはどうすればよいでしょうか。

A:
Windows API の WNetGetUser を使用します。Windows.pas で定義されたAPI 呼び出しのプロトタイプは以下のとおりです。

function WNetGetUser(lpName: PChar; lpUserName: PChar;
var lpnLength: DWORD): DWORD; stdcall;

この API を使用するには,第1引数に取得するユーザーのローカルデバイス名またはユーザーが接続を確立したネットワーク名を指定します。第2引数にはユーザー名を格納するバッファへのポインタを指定します。第3引数には第2引数のバッファの文字数を指定します。

procedure TForm1.Button1Click(Sender: TObject);
var
  BuffSize: DWord;
  Local,
  User: Array[0..30] of Char;
begin
  StrPCopy(Local, 'Microsoft Windows Network'); // 接続を確立したネットワーク名を指定
                                                // StrPCopy(Local, ''); でも可能
  FillChar(User, SizeOf(User), #0);
  BuffSize := SizeOf(User)-1;
  if NO_ERROR = WNetGetUser(Local, User, BuffSize) then
     Edit1.Text := StrPas(User);                // 取得したユーザー名を表示
end;

    キャンバスに描画するテキストの文字間隔を設定するには (98/08/03)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
キャンバスに描画するテキストの文字間隔を設定することはできませんか?

A:
TCanvas の TextOut メソッドなどを使ってテキストを描画する場合,API 関数のSetTextCharacterExtra を使用すれば文字間隔を設定できます。
この関数は,デバイスコンテキストを必要としますから,Canvas の Handle を使用します。次のコードは,TrackBar によって文字間隔を調節する例です。

{ PaintBox1のOnPaintイベント }
procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  with PaintBox1.Canvas do begin
    SetTextCharacterExtra(Handle, TrackBar1.Position);
    TextOut(10, 10, 'ABCDEFG');
  end;
end;

{ TrackBar1のOnChangeイベント }
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  PaintBox1.Invalidate;
end;

    Memo がアクティブになったときだけ CapsLock をオンにするには (98/08/03)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Memo がアクティブになったときだけ,CapsLock をオンにするにはどうしたらいいですか?

A:
CapsLock の設定は,SetKeyboardState によって行なうことができます。
SetKeyboardState を使用するには,GetKeyboardState によってあらかじめ全てのキー状態を取得してから,必要な箇所だけ変更します。
次の例は,Memo コンポーネントの OnEnter イベントで CapsLock をオンに設定し,OnExit イベントで CapsLock をオフに設定しています。

{ Memo1のOnEnterイベント }
procedure TForm1.Memo1Enter(Sender: TObject);
var
  Buf: TKeyboardState;
begin
  { 現在のキーボードの状態を取得します }
  GetKeyboardState(Buf);
  { CapsLockをオンにします }
  Buf[VK_CAPITAL] := $81;
  { 変更した内容を設定します }
  SetKeyboardState(Buf);
end;

{ Memo1のOnExitイベント }
procedure TForm1.Memo1Exit(Sender: TObject);
var
  Buf: TKeyboardState;
begin
  { 現在のキーボードの状態を取得します }
  GetKeyboardState(Buf);
  { CapsLockをオフにします }
  Buf[VK_CAPITAL] := $0;
  { 変更した内容を設定します }
  SetKeyboardState(Buf);
end;

    データファイルをダブルクリックすると関連付けたアプリケーションが起動するようにしたい (98/08/03)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
エクスプローラからデータファイルをダブルクリックすると関連付けたアプリケーションが起動するようにしたいのですが?

A:
アプリケーションの起動時の引数は,ParamStr で取得できます。
ParamStr(0) は実行プログラム名で,ParamStr(1) は選択したファイル名を返します。
Form の OnCreate イベントで ParamStr(1) が示すファイルを読み込めば,起動時に関連付ける事が出来ます。
以下の例では,テキストファイルをダブルクリックするか,アプリケーションアイコンにファイルをドラッグアンドドロップすることで,その内容をメモに張り付けます。
尚,ファイルの拡張子の関連付けは,マイコンピュータ[表示|オプション]のファイルタイプで,あらかじめ設定しておいて下さい。

procedure TForm1.FormCreate(Sender: TObject);
begin
  if ParamCount > 0 then
    Memo1.Lines.LoadFromFile(ParamStr(1));
end;

    ファイルの関連付け (98/12/2)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
アプリケーション中でファイルの関連付けを行うには?

A:
レジストリを変更してください。

以下のサンプルは,拡張子 .xxx を Notepad.exe と関連付けています。
uses に ShlObj と Registry を追加してください。

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TRegistry.Create do
  begin
    try
      RootKey:=HKEY_CLASSES_ROOT;
      OpenKey('\.xxx',True);                        // 拡張子.xxx を登録
      WriteString('','xxxFile');                    // 拡張子.xxx は xxxFile を参照
      OpenKey('\xxxFile',True);                     // xxxFile を登録
      WriteString('','xxxファイル');                // Explorer の説明用
      OpenKey('\xxxFile\DefaultIcon',True);         // Icon 参照キー
      WriteString('','"D:\WinNT40\Notepad.exe,0"'); // Icon の指定
      OpenKey('\xxxFile\shell\open\command',True);  // Application 参照キー
      WriteString('',                               // Application の指定
            '"D:\WinNT40\Notepad.exe" "%1"');
      SHChangeNotify(SHCNE_ASSOCCHANGED,            //システムに変更を通知
                     SHCNF_FLUSH,nil,nil);
    finally
      Free;
    end;
  end;
end;

    デフォルトプリンタの設定 (98/12/2)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
システムのデフォルトプリンターを永続的に変更したい。

A:

以下のような手順で,デフォルトプリンタを設定することができます。
Printer.PrinterIndex は,システムにインストールされているプリンタのうち, デフォルトに設定したいものを指定してください。
また,uses節に Printers を追加する必要があります。

procedure TForm1.Button1Click(Sender: TObject);
var
  DevMode: THandle;

  Device,Driver,Port: array[0..79] of Char;
  s: String;
begin
  Printer.PrinterIndex := 1;  // 目的のプリンタ
  Printer.GetPrinter(Device,Driver,Port,DevMode);
  S := Device + ',' + Driver + ',' + Port;
  WriteProfileString('windows','device',PChar(s));
  SendMessage(HWND_BROADCAST,WM_WININICHANGE,0,
         Longint(PChar('windows')));
end;

    CDのトレイをプログラムから閉じる方法を教えてください。 (98/12/2)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
CDのトレイをプログラムから開閉する方法を教えてください。

A:
CDのトレイをプログラムから開閉する場合には、TmediaPlayerコンポーネントを利用し行います。CDの閉じる場合にはWindows APIのmciSendCommandを使用する事で実現し、開く場合にはejectメソッドを利用します。
以下のコードは,ボタンを押された時にCDのトレイを閉く、または閉じるようになって います。

*mciSendCommandの定義とそれに必要な定義はMMSystemで行っておりますので,USES節にMMSystemを加える必要があります。

   // CDのトレイを閉じる
   function CDROM_Close(Drive : char): bool;
   var
      CD : TMediaPlayer;
      CD_Path : String;
   begin
      result := False;
      Application.ProcessMessages;
      CD_Path := Drive + ':\';
      if not boolean(GetDriveType(Pchar(CD_Path)) and DRIVE_CDROM) then
         exit;
      cd := TMediaPlayer.Create(nil);
      cd.Visible := false;
      cd.Parent := Application.MainForm;
      cd.Shareable := True;
      cd.DeviceType := dtCDAudio;
      cd.fileName := Drive + ':';
      cd.open;
      Application.ProcessMessages;
      mciSendCommand(cd.DeviceID,MCI_SET, MCI_SET_DOOR_CLOSED, 0);
      Application.ProcessMessages;
      cd.close;
      Application.ProcessMessages;
      cd.free;
      result := True;
   end;
   // CDのトレイを開く
   function CDROM_Eject(Drive : char): bool;
   var
      cd : TMediaPlayer;
      CD_Path : String;
   begin
      Result := False;
      Application.ProcessMessages;
      CD_Path := Drive + ':\';
      //ドライブがCDかをチェックする
      if not boolean(GetDriveType(Pchar(CD_Path)) and DRIVE_CDROM) then
         exit;
      //CDをejectするための処理
      cd := TMediaPlayer.Create(nil);
      cd.Visible := false;
      cd.Parent := Application.MainForm;
      cd.Shareable := True;
      cd.DeviceType := dtCDAudio;
      cd.fileName := Drive + ':';
      cd.Open;
      Application.ProcessMessages;
      cd.eject;
      Application.ProcessMessages;
      cd.close;
      Application.ProcessMessages;
      cd.free;
      Result := True;
   end;
   procedure TForm1.Button1Click(Sender: TObject);
   begin
      if not CDROM_Eject('H') then
         MessageDlg('CD ドライブではありません', mtInformation,[mbOk], 0);
   end;
   procedure TForm1.Button2Click(Sender: TObject);
   begin
      if not CDROM_Close('H') then
          MessageDlg('CD ドライブでエラーが発生しました。', mtInformation,[mbOk],
           0);
   end;

    アニメーションカーソルを使用するには、どのようにしたら良いのでしょうか? (99/01/08)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
アニメーションカーソルを使用するには,どのようにしたら良いのでしょうか?

A:
Windows APIのLoadImageを使用し読み込み後,そのハンドルをScreen変数のCursorsプロパティに設定します。以下の例を参考にしてください。

    procedure TForm1.Button1Click(Sender: TObject);
    var
       h : THANDLE;
    begin
       h := LoadImage(0,'c:\windows\cursors\Globe.ani',
                      IMAGE_CURSOR,0,0,
                      LR_DEFAULTSIZE or LR_LOADFROMFILE);
       if h = 0 then ShowMessage('カーソルが読み込めません')
       else
       begin
            Screen.Cursors[1] := h;
            Form1.Cursor := 1;
       end;
    end;

    DOS の環境変数を取得する方法 (99/01/08)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
環境変数とその値を取得したいのですが,どうすればいいですか?

A:
GetEnvironmentString 関数を使います。 Win16 環境では,GetDOSEnvironment 関数を使ってください。

以下のサンプルは,環境変数とその値を取得して,メモコントロールに追加しています。

    procedure TForm1.Button1Click(Sender: TObject);
     var
       p : pChar;
     begin
       Memo1.Lines.Clear;
       Memo1.WordWrap := false;
      {$IFDEF WIN32}
       p := GetEnvironmentStrings;
      {$ELSE}
       p := GetDOSEnvironment;
      {$ENDIF}
       while p^ <> #0 do begin
         Memo1.Lines.Add(StrPas(p));
         inc(p, lStrLen(p) + 1);
       end;
      {$IFDEF WIN32}
       FreeEnvironmentStrings(p);
      {$ENDIF}
     end;

    プログラムで[Caps]キーをロック/解除できますか? (99/01/08)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
プログラムで[Caps]キーをロック/解除できますか?

A:
SetKeyboardState 関数を利用します。
以下のサンプルはチェックボックスのチェックにしたがって,[Caps]キーをロック/解除しています。
この変更は,そのアプリケーション内で有効です。

    unit Unit1;

    interface

    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls;

    type
      TForm1 = class(TForm)
        CheckBoxCaps: TCheckBox;
        Memo1: TMemo;
        procedure CheckBoxCapsClick(Sender: TObject);
      private
        { Private 宣言 }
      public
        { Public 宣言 }
      end;
 
    var
      Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.CheckBoxCapsClick(Sender: TObject);
    var
      KeyState: TKeyboardState;
    begin
      GetKeyboardState(KeyState);
      KeyState[VK_CAPITAL] := Byte(CheckBoxCaps.Checked);
      SetKeyboardState(KeyState);
    end;

    end.

    DOS アプリケーションを呼び出して結果を取得したい (99/2/3)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Delphi で作ったアプリケーションから DOS アプリケーションを呼び出して,その実行結果を得たいのですが,どのようにすればいいでしょうか?
できれば,DOS プロンプトが開かないようにしたのですが。

A:
実行結果はリダイレクトで取得することができます。 DOS プロンプトの表示を抑止するには CreateProcess API 呼び出しの StartupInfo 構造体のパラメータを設定することで実現できます。以下のプログラムを参考にしてください。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure ExecProcess(Command, Dest: String);
var
  SI :TStartupInfo;
  PI :TProcessInformation;
begin
  FillChar(SI,SizeOf(SI),0);
  SI.cb := SizeOf(SI);
  SI.dwFlags:= STARTF_USESHOWWINDOW;     // DOS プロンプトが表示
  SI.wShowWindow := SW_HIDE;             // されるのを抑止する
  If Not CreateProcess(nil,
               PChar(Format('%s > %s',[Command,Dest])),
               nil,nil,False, 0, nil, nil, SI, PI) Then
    Raise Exception.Create('Error!');
  While WaitForSingleObject(PI.hProcess, 0) = WAIT_TIMEOUT Do
    Application.ProcessMessages;       // プロセス終了まで待機する
  CloseHandle(PI.hProcess);
end;


procedure TForm1.Button1Click(Sender: TObject);
const
  Command = 'C:\tools\lha.exe';           // 実行するDOSプログラム
var
  TempFileBuff: array[0..MAX_PATH] of Char;
  TempFileString: String;
begin
  GetTempFileName('.','tmp',0,TempFileBuff); // テンポラリファイル
  TempFileString := String(TempFileBuff);    // の作成
  try
    ExecProcess(Command,TempFileString);     // 実行
    Memo1.Lines.LoadFromFile(TempFileString);
  finally
    DeleteFile(TempFileString);           // テンポラリファイル削除
  end;
end;

end.

    プログラム上からFDをフォーマットしたいのですが、どのようにしたらよいのでしょうか? (99/2/3)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
プログラム上からFDをフォーマットしたいのですが,どのようにしたらよいのでしょうか?

A:
FDをフォーマットするには,ShellAPI のSHFormatDrive関数を使用する事で可能になります。
以下のサンプルプログラムを参考にしてください。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;
const
  SHFMT_DRV_A = 0;
  SHFMT_DRV_B = 1;

  SHFMT_ID_DEFAULT = $FFFF;

  SHFMT_OPT_QUICKFORMAT = 0;
  SHFMT_OPT_FULLFORMAT = 1;
  SHFMT_OPT_SYSONLY = 2;

  SHFMT_ERROR = -1;
  SHFMT_CANCEL = -2;
  SHFMT_NOFORMAT = -3;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;
  function SHFormatDrive(hWnd: HWND; Drive : WORD;
                         fmtID : WORD; Options : WORD): LongInt
           stdcall; external 'Shell32.dll' name 'SHFormatDrive';
var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
   FmtRes : longint;
begin
   try
      FmtRes := SHFormatDrive(Handle,SHFMT_DRV_A,SHFMT_ID_DEFAULT,
                              SHFMT_OPT_QUICKFORMAT);
      case FmtRes of
      SHFMT_ERROR : ShowMessage('ドライブフォーマット中にエラーが発生しました');
      SHFMT_CANCEL : ShowMessage('キャンセルされました');
      SHFMT_NOFORMAT : ShowMessage('未フォーマット')
      else
         ShowMessage('フォーマットが終了しました');
      end;
   except
   end;

end;

end.

    文字を斜めに表示したいのですが、どのようにしたらよいのでしょうか? (99/2/3)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
文字を斜めに表示したいのですが,どのようにしたらよいのでしょうか?

A:
Labelなどでは表示できませんので,Canvasに直接TextOutメソッドを利用し出力します。
その場合,使用するフォントは,Windows APIのCreateFontIndirectで論理フォントを作成し,そのFontを使用してCanvasに対して出力するようになります。
文字の回転情報はLogFont構造体によってCreateFontIndirectに情報を渡します。
下のサンプルプログラムを参考にしてください。

procedure TForm1.Button1Click(Sender: TObject);
var
   lf : TLogFont;
   tf : TFont;
begin
   with Form1.Canvas do
   begin
      Font.Name := 'MS Pゴシック';
      Font.Size := 24;
      tf := TFont.Create;
      tf.Assign(Font);
      GetObject(tf.Handle,sizeof(lf),@lf);
      lf.lfEscapement := 3150;
      lf.lfOrientation := 3150;
      tf.Handle := CreateFontIndirect(lf);
      Font.Assign(tf);
      tf.Free;
      TextOut(200,Height div 2,'文字の回転');
   end;
end;

    テキストの描画で背景を透過にすることはできますか? (99/2/3)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
テキストの描画で背景を透過にすることはできますか?

A:
Windows API の SetBkMode() を使います。下のサンプルを参考にしてください。

procedure TForm1.Button1Click(Sender: TObject);
var
  OldBkMode : integer;
begin
  with Form1.Canvas do begin
    Brush.Color := clRed;
    FillRect(Rect(0, 0, 100, 100));
    Brush.Color := clBlue;
    TextOut(10, 20, 'Not Transparent!');
    OldBkMode := SetBkMode(Handle, TRANSPARENT);
    TextOut(10, 50, 'Transparent!');
    SetBkMode(Handle, OldBkMode);
  end;
end;

    Windows に登録されているユーザ名や会社名を取得 (99/2/3)

該当するバージョン:Delphi 3.0/Delphi3.1,Delphi4

Q:
Windows に登録されているユーザ名や会社名を取得するにはどうしたらいいでしょうか?

A:
それらの情報はレジストリの "HKEY\CURRENT USER" セクションにあります。
以下のサンプルは TRegIniFile コンポーネントを使って, それらの情報を所得します。

uses Registry;

procedure TForm1.Button1Click(Sender: TObject);
var
  reg: TRegIniFile;
begin
  reg := TRegIniFile.create('SOFTWARE\MICROSOFT\MS SETUP (ACME)\');
  Memo1.Lines.Add(reg.ReadString('USER INFO',
                                 'DefName',
                                 'Frank Borland'));
  Memo1.Lines.Add(reg.ReadString('USER INFO',
                                 'DefCompany',
                                 'A Valued Borland Customer'));
  reg.free;
end;

    実行環境の画面設定が最大何色まで発色できるかを知るには (99/2/3)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
実行環境の画面設定が最大何色まで発色できるかを知るにはどうしたらいいですか?

A:
Windows API の GetDeviceCaps() を使って, 1ピクセルを表現するために必要なビット数が以下の式で求められます。

   GetDeviceCaps(Form1.Canvas.Handle, BITSPIXEL) *
   GetDeviceCaps(Form1.Canvas.Handle, PLANES)

最大発色数は 「1ピクセルを表現するために必要なビット数」を調べることで知ることができます。

ビット数と最大発色数の関係

最大表示色は以下の式で求められます。

   NumberOfColors := (1 shl
     (GetDeviceCaps(Form1.Canvas.Handle, BITSPIXEL) *
      GetDeviceCaps(Form1.Canvas.Handle, PLANES));

    システムが利用可能なドライブを知るには (99/2/3)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
システムが利用可能なドライブを知るには, どうしたらいいですか?

A:
Windows APIのGetLocalDrivesを使用します。
以下のサンプルは, システムが利用可能な論理ドライブのリストをメモコントロールに追加します。

procedure TForm1.Button1Click(Sender: TObject);
var
  ld : DWORD;
  i : integer;
begin
  ld := GetLogicalDrives;
  for i := 0 to 25 do begin
    if (ld and (1 shl i)) > 0 then
      Memo1.Lines.Add(Char(Ord('A') + i) + ':\');
  end;
end;

    Modemのステータスを取得するには、どのように行えば良いのでしょうか? (99/03/04)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Modemのステータスを取得するには,どのように行えば良いのでしょうか?

A:
Windows APIのGetCommModemStatusを利用します。
下のサンプルを参考にしてください。

    procedure TForm1.Button1Click(Sender: TObject);
    var
       CommPort : String;
       hCommFile : THandle;
       ModemStat : DWord;
    begin
         CommPort := 'COM1';
    // Commポートをオープンする
         hCommFile := CreateFile(PChar(CommPort),GENERIC_READ,
                                 0,nil,OPEN_EXISTING,
                                 FILE_ATTRIBUTE_NORMAL,0);
         if hCommFile = INVALID_HANDLE_VALUE then
         begin
              ShowMessage(CommPort+'がオープンできません');
              Exit;
         end;
         if GetCommModemStatus(hCommFile, ModemStat) then
         begin
              if ModemStat and MS_CTS_ON <> 0 then
                 ShowMessage('CTS ON');
              if ModemStat and MS_DSR_ON <> 0 then
                 ShowMessage('DSR ON');
              if ModemStat and MS_RING_ON <> 0 then
                 ShowMessage('Ring ON');
              if ModemStat and MS_RLSD_ON <> 0 then
                 ShowMessage('RLSD ON');
         end;
         CloseHandle(hCommFile);
    end;

    Windowsのゴミ箱にファイルを捨てるプログラムを作成したいのですが、どのようにプログラムしたら良いのでしょうか? (99/03/04)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Windowsのゴミ箱にファイルを捨てるプログラムを作成したいのですが,どのようにプログラムしたら良いのでしょうか?

A:
ShellAPIの SHFileOperation () をすることによって実現できます。
以下のサンプルコードを参考にしてください。

*サンプルではUSESにShellAPIを追加してください。

    procedure SendToRecycleBin(FileName: string);
    var  SHF: TSHFileOpStruct;
    begin
      with SHF do
      begin
          Wnd := Application.Handle;
          wFunc := FO_DELETE;
          pFrom := PChar(FileName+#0);
          fFlags := FOF_SILENT or FOF_ALLOWUNDO;
      end;
      SHFileOperation(SHF);
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if Opendialog1.Execute then
           SendToRecycleBin(Opendialog1.FileName);
    end;

    タスクトレイに常駐するアプリケーションの作成 (99/4/2)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
タスクトレイに常駐アプリケーションを作成したいのですが,どうのようにすればいいでしょうか?

A:
Win32API の Shell_NotifyIcon を使います。
以下のサンプルは, 実行するとタスクトレイに常駐します。
このとき, 左クリックでフォーム表示(タスクトレイから離別)また, 右クリックでアプリケーション終了します。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, Dialogs, ShellAPI, StdCtrls;

const
  WM_NotifyTasktray = WM_USER + 100;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private 宣言 }
    IsLiveTasktray: boolean;
    NotifyIcon: TNotifyIconData;
    procedure InitTasktray;
    procedure FinishTasktray;
    procedure MovetoTasktray;
    procedure LeaveTasktray;
  protected
    procedure WndProc(var Message: TMessage); override;
  public
    { Public 宣言 }
    constructor Create(AOwner: TComponent); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

constructor TForm1.Create(AOwner: TComponent);
begin
  inherited;
  IsLiveTaskTray := False;
end;


procedure TForm1.WndProc(var Message: TMessage);
begin

  if Message.Msg = WM_NotifyTasktray then
  begin
    case Message.LParam of
      WM_LBUTTONDOWN:
      begin
        LeaveTasktray;
      end;
      WM_RBUTTONDOWN:
        Close;
    end;
  end
  else
    inherited;
end;


procedure TForm1.InitTasktray;
begin
  if IsLiveTasktray then exit;
  with NotifyIcon do
  begin
    cbSize := SizeOf(TNotifyIconData);
    Wnd := Handle;
    uID := 1;
    uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
    uCallbackMessage := WM_NotifyTasktray;
    hIcon := Application.Icon.Handle;
    szTip := 'Tasktary...';
  end;
  Shell_NotifyIcon(NIM_ADD,@NotifyIcon);
  IsLiveTasktray := True;
end;

procedure TForm1.FinishTasktray;
begin
  if IsLiveTasktray = False then exit;
  with NotifyIcon do
  begin
    cbSize := SizeOf(TNotifyIconData);
    Wnd := Handle;
    uID := 1;
  end;
  Shell_NotifyIcon(NIM_DELETE,@NotifyIcon);
  IsLiveTasktray := False;
end;

procedure TForm1.MovetoTasktray;
begin
  InitTasktray;
  Hide;
end;

procedure TForm1.LeaveTasktray;
begin
  FinishTasktray;
  Show;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MoveToTasktray;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.ShowMainForm := False;
  MoveToTaskTray;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FinishTasktray;
end;

end.

    Q.PrintScreenキーが押された事を検出するには、どのように行えば良いのでしょうか? (99/4/2)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
PrintScreenキーが押された事を検出するには,どのように行えば良いのでしょうか?

A:
RegisterHotKey(Windows API)を利用し,PrintScreenキーのメッセージが受け取れるようにFormのOnCreateイベント内で登録し,OnDestroyイベントで登録を解放し,そのメッセージに対して処理できるようにメッセージ処理メソッドを定義します。以下のサンプルを参考にしていただきたいと思います。

type
  TForm1 = class(TForm)
     procedure FormCreate(Sender : TObject );
     procedure FormDestroy(Sender : TObject );
  private
    { Private 宣言 }
    procedure WMHotKey(var Msg : TWMHotKey); message WM_HOTKEY;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

const id_SnapShot = 101;

procedure TForm1.WMHotKey( var Msg: TWMHotKey );
begin
     if Msg.HotKey = id_SnapShot then
        ShowMessage('PrintScreenが押されました');
end;

procedure TForm1.FormCreate(Sender : TObject );
begin
      RegisterHotkey(Form1.Handle, id_SnapShot, 0, VK_SNAPSHOT);
end;

procedure TForm1.FormDestroy(Sender : TObject );
begin
      UnRegisterHotkey(Form1.Handle, id_SnapShot);
end;

    Q.タイトルバーにある閉じるアイコンを有効/無効にしたいのですが・・・ (99/4/2)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
タイトルバーにある閉じるアイコンを有効/無効にしたいのですが・・・

A:
Windows APIを使用し以下のコードで実現が可能になります。

1.無効にする例

procedure TForm1.Button2Click(Sender: TObject);
var
   hMenuHandle : HMENU;
begin
       hMenuHandle := GetSystemMenu(Form1.handle,False);
       if hMenuHandle <> 0 then
       EnableMenuItem(hMenuHandle, SC_CLOSE, (MF_BYCOMMAND + MF_DISABLED));
       DrawMenuBar(Form1.Handle);
end;

2.有効にする例

procedure TForm1.Button3Click(Sender: TObject);
var
   hMenuHandle : HMENU;
begin
       hMenuHandle := GetSystemMenu(Form1.handle,False);
       if hMenuHandle <> 0 then
       EnableMenuItem(hMenuHandle, SC_CLOSE, (MF_BYCOMMAND + MF_ENABLED));
       DrawMenuBar(Form1.Handle);
end;

    Delphiで作成したプログラムを終了させるとタスクバーに空白のボックスが残るのですが・・・ (99/6/4)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Delphiで作成したプログラムを終了させるとタスクバーに空白のボックスが残るのですが

A:
ウィンドウの拡張スタイルを変更している場合に,そのウィンドウをクローズする前に,拡張スタイルのリセットに失敗した場合に現象が発生します。この動作はWindows側の仕様により発生します。

(詳細は マイクロソフト株式会社ホームページ(http://www.microsoft.com/Japan)サポート技術情報,文書番号:J047671をご覧ください。)

この動作についてプログラム中で回避する場合には,フォームのOnDestroyメソッドにて以下のコードを実行してください。
タスクバーにウィンドウが残らないようになります。

ShowWindow(Application.Handle, SW_SHOW); 

    プログラム中でネットワークに接続されているかを判断したいのですが、どのように行えば良いのでしょうか? (99/6/4)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
プログラムでネットワークに接続されているかを判断したいのですが,どのように行えば良いのでしょうか?

A:
WINDOWS APIのGetSystemMetrics()を使用します。パラメータにSM_NETWORKを指定すると,ネットワークが存在する場合には,最下位ビットが 1 の値が,そうでないときは最下位ビットが 0 の値が返ります。
以下のコードを参考にしてください。

Procedure TForm1.Button1Click(Sender: TObject);
begin
    if GetSystemMetrics(SM_NETWORK) AND $01 = $01 then
       ShowMessage('Machine is attached to network')
    else
       ShowMessage('Machine is not attached to network');
end;

    Windows 95 のタスクバーの位置を知りたい (98/07/01)

該当するバージョン:Delphi 2.0,Delphi 3.0/Delphi3.1,Delphi4

Q:
Windows 95 のタスクバーの位置を知りたいのですが?

A:
Windows API の SHAppBarMessage を使います。
uses に ShellAPI を追加して下さい。

procedure TForm1.Button1Click(Sender: TObject);
var
  apbData : TAPPBARDATA;
begin
  apbData.cbSize := SizeOf(TAPPBARDATA);
  SHAppBarMessage(ABM_GETTASKBARPOS, apbData);

  { 取得した情報を表示 }
  with Memo1 do
  begin
    Clear;
    Lines.Add(Format('Left   : %d', [apbData.rc.left]));
    Lines.Add(Format('Right  : %d', [apbData.rc.right]));
    Lines.Add(Format('Top    : %d', [apbData.rc.top]));
    Lines.Add(Format('Bottom : %d', [apbData.rc.bottom]));
  end;
end;