« 2005年1月 | トップページ | 2006年1月 »

[Delphi] FontをIniファイルに保存する

procedure TForm1.ReadFromInifile(IniFilename: String);
var
 ini:TInifile;
 FStyle:TFontStyles;
 Fs :Byte absolute FStyle;
 FPitch:TFontPitch;
 Fp :Byte absolute FPitch;
begin
 ini:=TInifile.Create(IniFilename);
 try
  Fs:= ini.ReadInteger('Option','FontStyle',0);
  Fp:= ini.ReadInteger('Option','FontPitch',0);
  if Fs<>0 then FFont.Style:= FStyle;
  if Fp<>0 then FFont.Pitch:= FPitch;
  FFont.Color:= StringToColor(Ini.ReadString('Option','FontColor','clBlack'));
  FFont.Name := ini.ReadString('Option','FontName','MS ゴシック');
  FFont.Size := ini.ReadInteger('Option','FontSize',13);
  FFont.Charset:=ini.ReadInteger('Option','FontCharset',SHIFTJIS_CHARSET);
 finally
  ini.Free;
 end;
end;

procedure TForm1.WriteToInifile(IniFilename: String);
var
 ini:TInifile;
 FStyle:TFontStyles;
 Fs :Byte absolute FStyle;
 FPitch:TFontPitch;
 Fp :Byte absolute FPitch;
begin
 ini:=TInifile.Create(IniFilename);
 try
  FStyle:=FFont.Style;
  FPitch:=FFont.Pitch;
  ini.WriteInteger('Option','FontStyle',Fs);
  ini.WriteInteger('Option','FontPitch',Fp);
  ini.ReadString('Option','FontColor',ColorToString(FFont.Color));
  ini.WriteString('Option','FontName',FFont.Name);
  ini.WriteInteger('Option','FontSize',FFont.Size);
  ini.WriteInteger('Option','FontCharset',FFont.Charset);
 finally
  ini.Free;
 end;
end;

[BCB] アプリで表示されているフォームの一覧を取得する

TScreenのFormCountおよびFormsを使用します。

//ListBoxにFormの名前を一覧表示
for (int i=0;i<Screen->FormCount;i++) {
 TForm* Form=Screen->Forms[i];
 ListBox1->Items->Add(Form->Name);
}

[BCB] FontのStyleを取得する

CheckBox1->Checked=Memo1->Font->Style.Contains(fsBold);
CheckBox2->Checked=Memo1->Font->Style.Contains(fsItalic);
CheckBox3->Checked=Memo1->Font->Style.Contains(fsUnderline);

[BCB] 画像を開くダイアログのFilterとDefaultExt

GraphicFilter、GraphicExtensionを使うと画像ファイルに対応したフィルタ文字列、拡張子が取得できます。

OpenDialog1->DefaultExt = GraphicExtension(__classid(Graphics::TBitmap));
OpenDialog1->Filter = GraphicFilter(__classid(Graphics::TBitmap));

TBitmap以外に、Ticon、TMetafile、TGraphicが指定できます。

[BCB] ダイアログのオプションを設定する

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TOpenDialog *Dlg=new TOpenDialog(this);

 //オプションを設定
 Dlg->Options.Clear();
 Dlg->Options<<ofFileMustExist<<ofPathMustExist;

 if (Dlg->Execute()) {
  //なにかの処理
 }
 delete Dlg;
}

[BCB] ディレクトリを作成する

CreateDirでディレクトリ(フォルダ)が作成できます。深い階層のディレクトリを作成する場合は、親ディレクトリを順番に作っていく必要があります。この場合は、後述のForceDirectoriesを使うと便利です。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 AnsiString DirName = "C:\tmp\\test\\aaal";
 if (CreateDir(DirName)) {
  //作成に成功
 }
}

ForceDirectoriesを使うと深い階層のディレクトリをまとめて作成できます。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 AnsiString DirName = "C:\tmp\\test\\aaal";
 if (ForceDirectories(DirName)) {
  //作成に成功
 }
}

[BCB] 一時ファイルのファイル名を作成する

UINT GetTempFileName(
 LPCTSTR lpPathName, // ディレクトリ名
 LPCTSTR lpPrefixString, // 一時ファイル名の接頭辞
 UINT uUnique, // 整数
 LPTSTR lpTempFileName // 一時ファイル名を格納するバッファ
);

lpPrefixStringとuUniqueに基づいて一時ファイル名が作成される。

uUniqueに0を指定した場合は、システム時刻が使用され、実際にファイルが作成される。
uUniqueに0以外を指定すると、ファイル名だけが作られる。ファイル名が一意かどうかも保証されない。

[BCB] フォルダ内のファイルの一覧を取得

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TSearchRec Sr;
 int Attributes = faAnyFile; //検索対象とするファイルの属性

 if (FindFirst("C:\\tmp\\*.*", Attributes, Sr) == 0) {
  do {
   if ((sr.Attr & Attributes) == Sr.Attr) {
    ListBox1->Items->Add(Sr.Name);
    //Sr.Sizeでファイルのサイズを取得できる
   }
  } while (FindNext(Sr) == 0);
  FindClose(Sr);
 }
}

ファイルの属性に設定できる値。ORでつないで指定する。

faReadOnly書き込み禁止ファイル
faHidden隠しファイル
faSysFileシステムファイル
faVolumeIDボリュームファイル
faDirectoryディレクトリ
faArchiveアーカイブ
faAnyFileすべてのファイル

[BCB] ShellExecuteの使い方

関連付けられたアプリで開く
ShellExecute(NULL, "open", Filename.c_str(), NULL, NULL, SW_SHOWNORMAL);

 *openのほかにもprintとかも使える

アプリを指定して開く
ShellExecute(NULL, NULL, "notepad.exe", Filename.c_str(), NULL, SW_SHOWNORMAL);

[BCB] フォントのスタイルを設定する

//---------------------------------------------------------------------------
void __fastcall TForm1::LinkLabelMouseEnter(TObject *Sender)
{
 ((TLabel *)Sender)->Font->Color=clRed;
 ((TLabel *)Sender)->Font->Style=TFontStyles() << fsUnderline;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::LinkLabelMouseLeave(TObject *Sender)
{
 ((TLabel *)Sender)->Font->Color=clNavy;
 ((TLabel *)Sender)->Font->Style=TFontStyles();
}
//---------------------------------------------------------------------------

[BCB] ローカルホスト名とIPアドレスの取得

#include <System.hpp>
#include <IdWinsock.hpp>

//-----------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
 WORD wVersionRequested;
 TWSAData wsaData;

 wVersionRequested = MAKEWORD(1,1);
 WSAStartup(wVersionRequested,&wsaData);
}
//-----------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
 WSACleanup;
}
//-----------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 char Buf[256];
 PHostEnt p;

 p=gethostbyname(Buf);

 //IPアドレス
 Label1->Caption=(inet_ntoa)(*((PInAddr)p->h_addr_list[0]));
 //ローカルホスト名
 Label2->Caption=p->h_name;
}
//-----------------------------------------------------------------

[Delphi] 仮想キーコードで英数字を扱うには

Ord関数を使います。

procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word;
 Shift: TShiftState);
begin
 if Key=Ord('K') then begin
  //Kが押されたときの処理
 end;
end;

[Delphi] StatusBarに別のコンポーネントをのせたい

Parentプロパティを設定することでStatusBar上に別のコンポーネントを配置することができます。
Parentプロパティを設定した後は、Top、Leftプロパティを親コンポーネントの左上を(0,0)とした座標系で設定し直す必要があります。

procedure TForm1.FormCreate(Sender: TObject);
begin
 Button1.Parent:=StatusBar1;
 Button1.Top:=0;
 Button1.Left:=0;
end;

[Delphi] Memoで現在カーソルがある行を取得する

戻り値は1行目が0となります。

LineNo:=Memo1.Perform(EM_LINEFROMCHAR, -1, 0);

[Delphi] Memoで左右のマージンを設定する

以下の例では左に10ドット、右に20ドットのマージンを設定します。

Memo1.Perform(EM_SETMARGINS,
   EC_LEFTMARGIN or EC_RIGHTMARGIN,
   MAKELONG(10, 20));

[Delphi] Memoで座標から文字位置へ変換する

マウスカーソルの位置にある文字の位置(先頭からのバイト数)と行番号を表示する例です。

procedure TForm1.Memo1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
 Res:DWORD;
begin
 //座標から文字位置を取得
 Res := Memo1.Perform(EM_CHARFROMPOS, 0, MAKELONG(X, Y));

 //先頭からのバイト数を表示
 Label1.Caption := IntToStr(LOWORD(Res));
 //行数を表示
 Label2.Caption := IntToStr(HIWORD(Res));
end;

[Delphi] Memoで入力できる文字数を制限する

入力できるバイト数を制限する方法です。以下の例では32Kバイトに制限しています。

Memo1.Perform(EM_SETLIMITTEXT, 32*1024, 0);

[Delphi] MemoやRichEditをスクロールする

プログラムからMemoやRichEditをスクロールさせるには EM_SCROLL を使用します。

 //1ページ上へ
 Memo1.Perform(EM_SCROLL, SB_PAGEUP, 0);
 //1ページ下へ
 Memo1.Perform(EM_SCROLL, SB_PAGEDOWN, 0);
 //1行上へ
 Memo1.Perform(EM_SCROLL, _SB_LINEUP, 0);
 //1行下へ
 Memo1.Perform(EM_SCROLL, SB_LINEDOWN, 0);

EM_LINESCROLLを使用することもできます。

 //水平方向に3文字、垂直方向に2行スクロール
 Memo1.Perform(EM_LINESCROLL, 3, 2);

[Delphi] Memoで現在カーソルがある行までスクロールする

Memo1.Perform(EM_SCROLLCARET, 0, 0);

[Delphi] LabelのCaptionを改行したい

Labelに複数行の文字列を表示する方法です。

 Label1.Caption:='1行目'+#13#10+'2行目';

#13、#10はそれぞれCRコード、LFコードを表します。

[Delphi] Caps Lock、Num Lockの状態を調べる

Caps LockがOnになっているかを調べる例です。

begin
 if (GetKeyState(VK_CAPITAL) and $1 <> 0) then begin
  //Caps LockがOnになっている
 end else begin
  //Caps LockがOffになっている
 end;
end;

VK_CAPITALの代わりにVK_NUMLOCKとすればNum Lockの状態を取得できます。

[Delphi] 仮想キーコード

VK_LBUTTONVK_RBUTTONVK_CANCEL
VK_MBUTTONVK_BACKVK_TAB
VK_CLEARVK_RETURNVK_SHIFT
VK_CONTROLCtrlVK_MENUAltVK_PAUSE
VK_CAPITALVK_KANAVK_HANGUL
VK_JUNJAVK_FINALVK_HANJA
VK_KANJIVK_CONVERTVK_NONCONVERT
VK_ACCEPTVK_MODECHANGEVK_ESCAPE
VK_SPACEVK_PRIORVK_NEXT
VK_ENDVK_HOMEVK_LEFT
VK_UPVK_RIGHTVK_DOWN
VK_SELECTVK_PRINTVK_EXECUTE
VK_SNAPSHOTVK_INSERTVK_DELETE
VK_HELP'0'($30) ~ '9'($39)'A'($41) ~ 'Z'($5A)
VK_LWINVK_RWINVK_APPS
VK_NUMPAD0~VK_NUMPAD9VK_MULTIPLYVK_ADD
VK_SEPARATORVK_SUBTRACTVK_DECIMAL
VK_DIVIDEVK_F1~VK_F24VK_NUMLOCK
VK_SCROLLVK_PROCESSKEYVK_ATTN
VK_CRSELVK_EXSELVK_EREOF
VK_PLAYVK_ZOOMVK_NONAME
VK_PA1VK_OEM_CLEAR 

以下はGetAsyncKeyState() と GetKeyState()で使用するためのキーコード。右と左が区別できる。

VK_LSHIFTVK_RSHIFT
VK_LCONTROLVK_RCONTROL
VK_LMENUVK_RMENU

[Delphi] 2地点の緯度経度から方位を計算する

球面三角法を利用した方位の計算です。

uses Math;

// 引数
//  Lon1 地点1の経度(度)
//  Lat1 地点1の緯度(度)
//  Lon2 地点2の経度(度)
//  Lat2 地点2の緯度(度)
//
//   北緯は0~90度、南緯は-90~0度
//   東経は0~180度、西経は-180~0度
//
// 戻り値
//  地点1から見た地点2の方位(度)
function GetDirection(Lon1:Double; Lat1:Double; Lon2:Double; Lat2:Double):Double;
var
 Lon1Rad, Lat1Rad, Lon2Rad, Lat2Rad:Double;
 LonDiff:Double;
 X,Y:Double;
 Direction:Double;
begin
 //ラジアンに変換
 Lon1Rad := Lon1 * PI / 180;
 Lat1Rad := Lat1 * PI / 180;
 Lon2Rad := Lon2 * PI / 180;
 Lat2Rad := Lat2 * PI / 180;

 LonDiff := Lon2Rad - Lon1Rad;

 Y := Cos(Lat2Rad)*Sin(LonDiff);
 X := Cos(Lat1Rad)*Sin(Lat2Rad) - Sin(Lat1Rad)*Cos(Lat2Rad)*Cos(LonDiff);
 Direction := ArcTan2(Y, X);

 Direction:=Direction*180/PI;
 if Direction < 0 then Direction:=Direction+360;

 Result:=Direction;
end;

[Delphi] 2地点の緯度経度からその間の距離を計算する

Hubenyの簡易式を使用した方法です。

uses Math;

// 引数
//  Lon1 地点1の経度(度)
//  Lat1 地点1の緯度(度)
//  Lon2 地点2の経度(度)
//  Lat2 地点2の緯度(度)
//
//   北緯は0~90度、南緯は-90~0度
//   東経は0~180度、西経は-180~0度
//
// 戻り値
//  2地点間の距離(km)
function GetHubenyDistance(Lon1:Double; Lat1:Double; Lon2:Double; Lat2:Double):Double;
var
 Lon1Rad, Lat1Rad, Lon2Rad, Lat2Rad:Double;
 LatAveRad, LatDiff, LonDiff:Double;
 Meridian, PrimeVertical:Double;
 X,Y:Double;
begin
 //ラジアンに変換
 Lon1Rad := Lon1 * PI / 180;
 Lat1Rad := Lat1 * PI / 180;
 Lon2Rad := Lon2 * PI / 180;
 Lat2Rad := Lat2 * PI / 180;

 LatAveRad := (Lat1Rad + Lat2Rad) / 2;
 LatDiff := Lat1Rad - Lat2Rad;
 LonDiff := Lon1Rad - Lon2Rad;

 //子午線曲率半径
 Meridian := 6334834 / Sqrt(Power(1 - 0.006674*Sin(LatAveRad)*Sin(LatAveRad),3));
 //卯酉線曲率半径
 PrimeVertical := 6377397 / Sqrt(1 - 0.006674*Sin(LatAveRad)*Sin(LatAveRad));

 //ヒュベニの公式
 X := Meridian*LatDiff;
 Y := PrimeVertical*Cos(LatAveRad)*LonDiff;

 Result := Sqrt(X*X + Y*Y);
end;

[Delphi] 修正ユリウス通日と年月日の変換

uses Math;

//年月日から修正ユリウス通日へ
function YMD2MJD(y,m,d:Integer):Integer;
begin
 if (m = 1) or (m = 2) then begin
  y:=y-1;
  m:=m+12;
 end;
 //フリーゲルの公式
 Result:=Floor(365.25*y) + (y div 400) - (y div 100) + Floor(30.59*(m-2)) + d -678912;
end;

//修正ユリウス通日から年月日へ
procedure MJD2YMD(mjd:Integer; var y,m,d:Integer);
var
 k:Integer;
begin
 y := Floor( (mjd - 15078.2) / 365.25 );
 m := Floor((mjd - 14956.1 - Floor(y*365.25)) / 30.6001 );
 d := mjd - 14956 - Floor(y*365.25) - Floor(m*30.6001);
 If (m = 14) or (m = 15) then k := 1
 else k := 0;
 y := y + k + 1900;
 m := m - 1 - k*12;
end;

ユリウス通日は紀元前4713年1月1日からの経過日数を表します。修正ユリウス通日はユリウス通日から2400000.5引いたものでMJD(Modified Julian Day)と略されます。ユリウス通日は2つの日付間の日数を計算したりするの使えます。とはいっても、標準で用意されている関数があるのでわざわざ実装することはないと思いますが。ご参考まで。 

[Delphi] 日付から曜日を計算する方法

y年m月d日の曜日(日曜が0、...、土曜が6)を求める方法です。
1月、2月は前年の13月、14月として計算します。

begin
 if (m = 1) or (m = 2) then begin
  y:=y-1;
  m:=m+12;
 end;
 Result:=(y + (y div 4) - (y div 100) + (y div 400) +((13*m+8) div 5) + d) mod 7;
end;

この式はZellerの公式というものです。
1582年10月15日(グレゴリオ暦施行日)以前については有効ではありませんのでご注意ください。

[Delphi] 起動引数を取得する

起動引数をListBoxに一覧表示する例です。

var
 i:Integer;
begin
 for i:=1 to ParamCount do begin
  ListBox1.Items.Add(ParamStr(i));
 end;
end;

ParamCountは引数の数で、ParamStr(i) で実際の引数が取得できます。ParamStr(0) はアプリケーション自身のファイル名で、ParamStr(1) が1つ目の引数になります。

[Delphi] キーが押されているか調べる

あるキーが押されているかどうかは GetKeyState 関数を使います。引数には仮想キーコードを渡します。キーが押されている場合は戻り値の最上位1ビットが1にセットされます。 Caps Lockなどトグルするキーの状態は最下位の1ビットを調べます。

begin
 if (GetKeyState(VK_F1) < 0) then begin
  //キーが押されているときの処理
 end;
end;

まさにそのとき、キーが押されているかを取得するにはGetAsyncKeyStateを使ったほうがよいかもしれません。

[Delphi] コントロールパネルを表示する

コントロールパネルを表示するには以下のようにします。

WinExec('control.exe', SW_SHOW);

さらに、コントロールパネル内の「マウスのプロパティ」を表示したいときは、

WinExec('control.exe main.cpl',SW_SHOW);

とします。 ほかにもmain.cplの部分を書き換えることでいろいろな設定ダイアログが表示できます。

WindowsXPの例

access.cplユーザ補助のオプション
appwiz.cplプログラムの追加と削除
bthprops.cplBluetooth
desk.cpl画面のプロパティ
firewall.cplWindowsファイアウォール
hdwwiz.cplハードウェアの追加ウィザード
inetcpl.cplインターネットのプロパティ
irprops.cplワイヤレスリンク
joy.cplゲームコントローラ
main.cplマウスのプロパティ
mmsys.cplサウンドとオーディオデバイスのプロパティ
netsetup.cplネットワークセットアップウィザード
nusrmgr.cplユーザアカウント
powercfg.cpl電源オプションのプロパティ
sysdm.cplシステムのプロパティ
telephon.cpl電話とモデムのオプション
timedate.cpl日付と時刻のプロパティ
wscui.cplWindowsセキュリティセンター
wuaucpl.cpl自動更新

[Delphi] INIファイルの読み書き

INIファイルを読み書きするにはTIniFileクラスを使うと便利です。

uses IniFiles;

procedure TForm1.Button1Click(Sender: TObject);
var
 ini:TIniFile;
 Str:String;
begin
 ini:=TIniFile.Create('test.ini');
 try
  //INIファイルから文字列を読み込む
  ini.ReadString:=('Section','TestFile','C:\tmp\tmp.txt');
 finally
  ini.Free;
 end;
end;

値を読む

ReadString文字列値
ReadBool論理値
ReadDate日付値
ReadTime時刻値
ReadDateTime日付時刻値
ReadFloat浮動小数点値
ReadInteger整数値

値を書く

WriteString文字列値
WriteBool論理値
WriteDate日付値
WriteTime時刻値
WriteDateTime日付時刻値
WriteFloat浮動小数点値
WriteInteger整数値

管理

ValueExistsデータが存在するか
SectionExistsセクションが存在するか
DeleteKeyデータを削除
EraseSectionセクションをすべて削除
ReadSectionsすべてのセクション名を読み出す
ReadSectionセクション内にあるすべてのキー名を読み出す
ReadSectionValuesセクション内にあるすべてのキーと値を読み出す

[BCB] シャットダウンダイアログを表示する

タスクバーを閉じるとシャットダウンのダイアログが表示されます。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 HWND hWnd;

 hWnd=FindWindow("Shell_TrayWnd", NULL); //タスクバーのハンドルを取得
 SendMessage(hWnd, WM_CLOSE, 0, 0);
}

[Delphi] シャットダウンダイアログを表示する

タスクバーを閉じるとシャットダウンのダイアログが表示されます。

provedure TForm1.ShutdownWindows;
var
 h : HWND;
begin
 h := FindWindow('Shell_TrayWnd', nil); //タスクバーのハンドルを取得
 SendMessage(h, WM_CLOSE, 0, 0);
end;

[Delphi] 動的に配列を作成する

var
 Arry: array of Char; //1次元配列
 Arry2: array of array of Char; //2次元配列
begin
 //1次元配列の場合
 SetLength(Arry, 256);

 //2次元配列の場合
 SetLength(Arry2, 30);
 SetLength(Arry2[0], 100);
 SetLength(Arry2[1], 100);
end;

[Delphi] ひらがなとカタカナを変換

//ひらがなからカタカナ
function TForm1.HiraToKata(Str : String) : String;
var
 Buf:array [0 .. 1023] of Char;
begin
 LCMapString(GetUserDefaultLCID, LCMAP_KATAKANA, PChar(Str), Length(Str)+1, Buf, 1024);
 Result:=String(Buf);
end;

//カタカナからひらがな
function TForm1.KataToHira(Str : String) : String;
var
 Buf:array [0 .. 1023] of Char;
begin
 LCMapString(GetUserDefaultLCID, LCMAP_HIRAGANA, PChar(Str), Length(Str)+1, Buf, 1024);
 Result:=String(Buf);
end;

[Delphi] 半角と全角を変換する

//半角から全角
function TForm1.HanToZen(Str : String) : String;
var
 Buf:array [0 .. 1023] of Char;
begin
 LCMapString(GetUserDefaultLCID, LCMAP_FULLWIDTH, PChar(Str), Length(Str)+1, Buf, 1024);
 Result:=String(Buf);
end;

//全角から半角
function TForm1.ZenToHan(Str : String) : String;
var
 Buf:array [0 .. 1023] of Char;
begin
 LCMapString(GetUserDefaultLCID, LCMAP_HALFWIDTH, PChar(Str), Length(Str)+1, Buf, 1024);
 Result:=String(Buf);
end;

[Delphi] 文字が全角か半角か調べる

//'ああああ'の3バイト目を調べる例
case ByteType('ああああ',3) of
 mbSingleByte: Lable1.Caption:='半角です';
 mbLeadByte: Lable1.Caption:='全角の1バイト目です';
 mbTrailByte: Label1.Caption:='全角の2バイト目です';
end;

全角1バイト目の文字集合であるLeadBytesを利用する方法もあります。

Str:='aああ';
if (Str[3] in LeadBytes) then Label1.Caption:='全角の1バイト目です';

[Delphi] ListBoxをスクロールさせる

ListBoxのTopIndexプロパティを設定します。
TopIndexプロパティを使うと、リストボックスの一番上に表示したい項目を設定することができます。

[Delphi] ListBoxに横スクロールバーをつける

ListBoxに横スクロールバーを表示する例です。ListBoxの中で一番、幅の長いアイテムを見つけてから、それにあわせて横スクロールバーを表示しています。

procedure TForm1.Button1Click(Sender: TObject);
var
 i:Integer;
 MaxWidth:Integer;
 TextWidth:Integer;
begin
 //一番、幅の長い文字列を調べる
 MaxWidth:=0;
 for i:=0 to ListBox1.Items.Count-1 do begin
  TextWidth:=ListBox1.Canvas.TextWidth(ListBox1.Items[i]);
  if (MaxWidth < TextWidth) then MaxWidth:=TextWidth;
 end;

 //横スクロールバーを表示
 ListBox1.Perform (LB_SETHORIZONTALEXTENT, MaxWidth+10, 0);
end;

[Delphi] 文字列を表示するのに必要な幅や高さが知りたい

CanvasのTextWidthメソッドを使うと、その文字列を表示するために必要な幅がわかります。同じようにCanvasのTextHeightメソッドで表示するのに必要な高さがわかります。

TextWidth:=Form1.Canvas.TextWidth('aaaああああ');
TextHeight:=Form1.Canvas.TextHeight('aaaああああ');

[BCB] ProgressBarの色を変える

以下のようにするとProgressBarのバーの部分の色が変えられます。

#include <CommCtrl.h>

void __fastcall TForm1::FormCreate(TObject *Sender)
{
 SendMessage(ProgressBar1->Handle, PBM_SETBARCOLOR, 0, clTeal);
 //SendMessage(ProgressBar1->Handle, PBM_SETBARCOLOR, 0, RGB(255,0,0));
}

[Delphi] ProgressBarの色を変える

以下のようにするとProgressBarのバーの部分の色が変えられます。

uses CommCtrl;

procedure TForm1.FormCreate(Sender: TObject);
begin
 SendMessage(ProgressBar1.Handle, PBM_SETBARCOLOR, 0, clTeal);
 //SendMessage(ProgressBar1.Handle, PBM_SETBARCOLOR, 0, RGB(255,255,0));
end;

[Delphi] ファイル名をドライブ、パス、ファイル名に分解

uses FileCtrl;

var
 Drive:Char;
 DirPart:String;
 FilePart:String;
begin
 ProcessPath(Application.ExeName,Drive,DirPart,FilePart);
end;

とすると各変数には次のような値が入る

Drive:'C'
DirPart:'\Program Files\Delphi5\Projects'
FilePart:'Project1.exe'

[Delphi] ファイル名が決められた幅に収まるようにしたい

Formのキャプションにファイル名を表示するときなどに、Formの幅にうまく収まるように表示させたいときがあります。そういうときは以下の関数を使います。

uses FileCtrl;
Label1.Caption:=MinimizeName(Application.ExeName,Canvas,200);

とするとラベルには以下のように表示されます。

C:\...\Delphi5\Projects\Project1.exe

[Delphi] フォルダ選択ダイアログを表示する

uses FileCtrl;

var
 Str:String;
begin
 if SelectDirectory('フォルダを選択してください','',Str) then begin
  //Strに選択されたフォルダ名がはいっている
 end
end

[Delphi] フォルダが存在するか調べる

if DirectoryExists(Filename) then begin
 //フォルダが存在したときの処理
end;

[Delphi] ファイルが存在するか調べる

if FileExists(Filename) then begin
 //ファイルが存在したときの処理
end;

[Delphi] ファイル名からフォルダ部分だけを取り出す

FileDir:=IncludeTrailingBackSlash(ExtractFilePath(Filename));

IncludeTrailingBackSlashを使うと必ず末尾が\になるようにできます。

Delphi6以降ではIncludeTrailingBackSlashの代わりにIncludeTrailingPathDelimiterを使うようにします。IncludeTrailingPathDelimiterはWindows では '\",Linux では '/'でパス名が終わるようにしてくれます。

FileDir:=IncludeTrailingPathDelimiter(ExtractFilePath(Filename));

[Delphi] 知っていると便利なIDEのショートカット その2

Delphi 5 です。

エディタ(デフォルト設定)

Ctrl+Eインクリメンタルサーチ
Ctrl+F検索
Ctrl+R置換
Ctrl+T1語を削除する
Ctrl+Y1行を削除する
Ctrl+Spaceコード補完ポップアップ
Ctrl+Shift+↑宣言にジャンプ
Ctrl+Shift+↓コードにジャンプ
Ctrl+Shift+C宣言やコードを補完(すごく便利)
Ctrl+Shift+GGUIDを挿入
Ctrl+Shift+Y行の終わりまで削除
Ctrl+Shift+Spaceパラメータポップアップ
Alt+[、]対応する区切り記号を探す
Ctrl+O+Aカーソル位置のファイルを開く
Ctrl+O+G指定行に移動
Ctrl+O+U大文字と小文字を切り替え

システム(デフォルト設定)

F1ヘルプ
F4カーソル位置まで実行
F5ブレークポイントの追加
F7トレース実行
F8ステップ実行
F9実行
F11オブジェクトインスペクタ
F12フォーム/ユニット切り替え
Alt+0ウィンドウの一覧
Alt+F2デバッグ CPU
Alt+F11ユニットを使う
Ctrl+F2プログラムの終了
Ctrl+F9コンパイル
Ctrl+F11プロジェクトを開く
Shift+F11プロジェクトに追加

[Delphi] 知っていると便利なIDEのショートカット

Delphi 5 です。

フォームのデザイン

Ctrl+矢印キー 1 ピクセルだけ移動
Shift+矢印キー1 ピクセルだけサイズを変更
Ctrl+Shift+矢印キー1 グリッドだけ移動
F12フォームとユニットファイルを切り替え
Ctrl+F12「ユニットの表示」ダイアログを表示
Shift+F12「フォームの表示」ダイアログを表示
Enter「オブジェクトインスペクタ」にフォーカスが移動

オブジェクトインスペクタ

Tabオブジェクトインスペクタでプロパティ列と値列を切り替え
Tab+英字その英字で始まる最初のプロパティにジャンプ
Ctrl+Tabプロパティタブとイベントタブを切り替え
Alt+↓プロパティのドロップダウンリストを開く
Ctrl+↓オブジェクトのドロップダウンリストを開く
Ctrl+Enter[...]ボタンを選択

[BCB] STLのヘルプはどこ?

C++Builder 6.0 の場合は、以下の場所にあります。

$(BCB)/Help/index.html

*$(BCB)はC++Builderをインストールしたフォルダの意味です。

[BCB] C++Builder Directを表示したくない

「ツール」-「環境オプション」の「C++Builder Direct」タブで
 「ネットワーク経由で自動的に確認を行う」のチェックを外す

[Delphi] Delphi Directを表示したくない

「ツール」-「環境オプション」の「Delphi Direct」タブで
 「ネットワーク経由で自動的に確認を行う」のチェックを外す

[BCB] MDIで子画面を閉じる方法

通常は子画面の×ボタンを押しても最小化されるだけで消えません。
本当に閉じたい場合は、OnCloseの中に次の一行を書きます。

Action = caFree;

[BCB] 使えるデータ型とサイズ

BCBで使用できる32ビットのデータ型とサイズ

バイト範囲
unsigned char10 ≦ X ≦ 255
char1-128 ≦ X ≦ 127
short int2-32,768 ≦ X ≦ 32,767
unsigned int40 ≦ X ≦ 4,294,967,295
int4-2,147,483,648 ≦ X ≦ 2,147,483,647
enum4-2,147,483,648 ≦ X ≦ 2,147,483,647
unsigned long40 ≦ X ≦ 4,294,967,295
long4-2,147,483,648 ≦ X ≦ 2,147,483,647
float41.18 * 10^-38 < |X| < 3.40 * 10^38
double82.23 * 10^-308 < |X| < 1.79 * 10^308
long double103.37 * 10^-4932 < |X| < 1.18 * 10^4932

[LaTeX] 文字のサイズ

大きい順に並べると

\Huge 
\huge 
\LARGE 
\Large 
\large 
\normalsize 標準の大きさ
\small 
\footnotesize 脚注の大きさ
\scriptsize 上付き下付きの大きさ
\tiny 

[BCB] ファイルに対応付けられているアイコンを取得する

SHFILEINFO shfi;

SHGetFileInfo(Filename.c_str(), FILE_ATTRIBUTE_ARCHIVE, &shfi,
         sizeof(SHFILEINFO),
         SHGFI_ICON | SHGFI_LARGEICON | SHGFI_TYPENAME);
Image1->Picture->Icon->Handle=shfi.hIcon;

[Delphi] フォームを最前面に表示する

//最前面に表示する
SetWindowPos(Handle,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE);

//普通に戻す
SetWindowPos(Handle,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE);

FormStyleによって最前面にするとちらつくが、上記の方法だとちらつかずにできる。

[BCB] Delphiのpasファイルを使いたい

Delphi で作成した関数を C++Builder で使用するには pas ファイルから objファイルと hppファイル を生成する必要があります。一度、pasファイルをプロジェクトに加え、「コンパイル」するとこれらのファイルが作成されますので、必要な箇所でhppファイルをインクルードします。

[Delphi] Wavを鳴らす

uses MMSystem;

SndPlaySound('test.wav',SND_ASYNC);

[BCB] アイコンファイルを開く

TIcon *Icon;

Icon=new TIcon;
Icon->LoadFromFile(LoadFilename);
Bmp->Width=Icon->Width;
Bmp->Height=Icon->Height;
Bmp->Canvas->Draw(0,0,Icon);
delete Icon;

[BCB] 関数をプロパティに代入するには

関数型を __closure という指定をつけてtypedefします。

typedef void __fastcall (__closure *TMyEvent)(int State);

class TMyClass
{
private:
 TMyEvent *FOnMyEvent;
  :
public:
 __property TMyEvent *OnMyEvent={read=FOnMyEvent, write=FOnMyEvent};
  :
};

[BCB] StringGridで追加した行がちょうどいいとこに表示されるように

for (int i=0;i<100;i++) {
 StringGrid1->RowCount=i+1; //行を追加
 StringGrid1->Cells[0][i]=IntToStr(i); //適当にデータを入れる

 //いいところにスクロール
 StringGrid1->TopRow=StringGrid1->RowCount-StringGrid1->VisibleRowCount;
}

TStringGrid::TopRowは表示画面で一番上に表示されている行のインデックスを表します。ここで一番上というのはスクロールできない固定行は除いて一番上の行という意味です。 またTStringGrid::VisibleRowCountは画面上に表示されている行のうち、スクロールできない固定行は除いた行数を表します。

[BCB] AnsiString型はchar *に変換できない!?

AnsiStringをchar *に代入したいときは、c_str() を使用します。

char *dest;
AnsiString src="test";

//dest=src; これはエラーになる
dest=src.c_str();

c_str() を使う際の注意点。
AnsiString::c_str() は一時的な領域をを指すポインタを返します。このポインタは,それが使われている文の実行が終了すると不定になってします。 そのため、 c_str() が指す領域を変更するような処理をしてはいけません。

[BCB] 動的に配列を生成する

char *buf=NULL;

buf=new char[1024];
/* bufを使った処理 */
delete [] buf;

確保した配列を解放するときに[ ]を付け忘れると、配列の最初の要素だけが解放されることになります。書き忘れないように注意しましょう。

[BCB] int型やlong型の最大値

定数名説明
CHAR_MINchar型の最小値
CHAR_MAXchar型の最大値
UCHAR_MAXunsigned char型の最大値
SHRT_MINshort型の最小値
SHRT_MAXshort型の最大値
USHRT_MAXunsigned short型の最大値
LONG_MINlong型の最小値
LONG_MAXlong型の最大値
ULONG_MAXunsigned long型の最大値
INT_MINint型の最小値
INT_MAXint型の最大値
UINT_MAXunsigned int型の最大値

[BCB] MAX、MINマクロ

#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

[Delphi] エクスプローラからのDrag & Dropに対応する

type
 TForm1 = class(TForm)
  procedure FormShow(Sender: TObject);
  procedure FormCreate(Sender: TObject);
 private
{ Private 宣言 }
  procedure Nantoka(Filename:String);
  procedure WMDropFiles(var Msg: TWMDropFiles); Message WM_DropFiles;
 public
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}
procedure TForm1.WMDropFiles(var Msg: TWMDropFiles);
var
 FileName: Array[0..MAX_PATH] of Char;
begin
 DragQueryFile(Msg.Drop, 0, FileName, SizeOf(FileName));
 Nanntoka(String(FileName));
 DragFinish(Msg.Drop);
end;

procedure TForm1.FormShow(Sender: TObject);
begin
 if ParamCount<>0 then Nantoka(ParamStr(1));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 DragAcceptFiles(Form1.Handle, True);
end;

[Delphi] 外部プロセスを起動する

var
HAPP:HWND; //起動したアプリケーションのハンドルを保持する

function EnumWindowsProc(HWND:THandle; lParam:LongInt) : BOOL; stdcall;
var
 dwProcessID:Integer;
begin
 Result:=True;
 if (GetWindow(HWND,GW_OWNER)=0) and IsWindowVisible(HWND) then begin
  GetWindowThreadProcessID(HWND,@dwProcessID);
  if (dwProcessID=lParam) then begin
   HAPP:=HWND;
   Result:=False;
  end;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 si:TStartupInfo;
 pi:TProcessInformation;
begin
 GetStartupInfo(si);
 CreateProcess(nil,PChar('Notepad.exe'),nil,nil,False,
    CREATE_DEFAULT_ERROR_MODE,nil,PChar(GetCurrentDir),si,pi);

 WaitForInputIdle(pi.hProcess,INFINITE);

 EnumWindows(@EnumWindowsProc,pi.dwProcessID);
end;

[Delphi] Formを最背面に表示する

type
 TForm1 = class(TForm)
  procedure FormActivate(Sender: TObject);
 private
  { Private 宣言 }
 public
  { Public 宣言 }
  procedure WMWindowPosChanging(var Msg : TWMWindowPosChanging); message WM_WINDOWPOSCHANGING;
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormActivate(Sender: TObject);
begin
 SetWindowPos(Handle,HWND_BOTTOM,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE);
end;

procedure TForm1.WMWindowPosChanging(var Msg: TWMWindowPosChanging);
begin
 Msg.WindowPos.hwndInsertAfter:=HWND_BOTTOM;
end;

end.

[Delphi] 搭載されているメモリ量を取得

function TForm1.GetAvailableMemory: String;
var
 ms:TMemoryStatus;
begin
 ms.dwLength:=SizeOf(TMemoryStatus);
 GlobalMemoryStatus(ms);
 Result:=IntToStr(ms.dwTotalPhys);
end;

TMemoryStatusには、以下のような値が格納されています。

dwLength構造体のサイズ
dwMemoryLoad利用中のメモリの割合
dwTotalPhys物理メモリのバイト数
dwAvailPhys物理メモリの空きバイト数
dwTotalPageFileページングファイルのバイト数
dwAvailPageFileページングファイルの空きバイト数
dwTotalVirtualアドレス空間のユーザバイト数
dwAvailVirtual空きユーザバイト数

[Delphi] JpegとBmpの変換

use節にJpegを追加

uses Jpeg;

//BmpからJpeg
procedure TForm1.Button1Click(Sender: TObject);
Var
Jpg : TJpegImage;
Bmp : TBitMap ;
begin
 Jpg :=TJpegImage.Create;
 Bmp :=TBitmap.Create;

 Bmp.LoadFromFile('C:\From.bmp');
 Jpg.Assign(BMP);
 Jpg.SaveToFile('C:\To.jpg' );

 Bmp.Free ;
 Jpg.Free;
end;

//JpegからBmp
procedure TForm1.Button1Click(Sender: TObject);
var
 Jpg : TJpegImage; 
 Bmp : TBitmap;
begin
 Jpg :=TJpegImage.Create ;
 Bmp :=TBitmap.Create;

 Jpg.LoadFromFile('From.jpg');
 Bmp.Assign(JPG);
 Bmp.SaveToFile('To.bmp')

 Jpg.Free;
 Bmp.Free ;
end;

[BCB] EXEファイルだけで実行できるようコンパイルする

デフォルトの設定でプロジェクトをコンパイルすると、別のパソコンにexeファイルだけをコピーしてもファイルが足りないと言われて実行できないことがある。exeだけで実行できるようにコンパイルするには、

「プロジェクト」-「オプション」で
  「パッケージ」タブの「実行時パッケージを使って構築」のチェックを外す
  「リンカ」タブの「共有RTL DLLを使う」のチェックを外す

[BCB] バージョン情報の取得

void GetFileVersionInformation(char *Result,int Size)
{
  LPVOID lpStr1 = NULL;
  LPVOID lpStr2 = NULL;
  WORD* wTmp;
  DWORD dwHandle_dammy = NULL;
  UINT nRet;
  UINT dwLength;
  char sFileName[1024];
  char sTmp[1024];
  char *sInfo;

  if ((Result==NULL) || (Size==0)) return;

  memset(sFileName,0x00,1024);
  GetModuleFileName(NULL,sFileName,1024);

  //バージョン情報のサイズを取得する
  DWORD dwInfoSize = GetFileVersionInfoSize((char*)(LPCTSTR)sFileName, &dwHandle_dammy);
  LPVOID* pVersionInfo = new LPVOID[dwInfoSize];

  nRet = GetFileVersionInfo((char*)(LPCTSTR)sFileName, dwHandle_dammy, dwInfoSize, pVersionInfo);
  if(nRet){
    //言語IDとキャラクタIDを取得する
    nRet = VerQueryValue(pVersionInfo, "\\VarFileInfo\\Translation", &lpStr1, &dwLength);
    if(nRet){
      wTmp = (WORD*)lpStr1;

      //バージョン情報を取得する
      StringCbPrintfA(sTmp,1024,"\\StringFileInfo\\%04x%04x\\FileVersion", *wTmp, *(wTmp + 1));
      nRet = VerQueryValue(pVersionInfo, sTmp, &lpStr2, &dwLength);

      if(nRet) sInfo = (char*)lpStr2;
      else sInfo = "";

      strncpy(Result,sInfo,Size-1);
    } else {
      strncpy(Result,"",Size-1);
    }
  } else {
    strncpy(Result,"",Size-1);
  }
  delete[] pVersionInfo;
}


=====
AnsiString 版

AnsiString GetFileVersionInformation(void)
{
  LPVOID lpStr1 = NULL;
  LPVOID lpStr2 = NULL;
  WORD* wTmp;
  DWORD dwHandle_dammy = NULL;
  UINT nRet;
  UINT dwLength;
  AnsiString sTmp;
  AnsiString sInfo;
  AnsiString Result="";

  //バージョン情報のサイズを取得する
  DWORD dwInfoSize = GetFileVersionInfoSize(Application->ExeName.c_str(), &dwHandle_dammy);
  LPVOID* pVersionInfo = new LPVOID[dwInfoSize];

  nRet = GetFileVersionInfo(Application->ExeName.c_str(), dwHandle_dammy, dwInfoSize, pVersionInfo);
  if(nRet){
    //言語IDとキャラクタIDを取得する
    nRet = VerQueryValue(pVersionInfo, "\\VarFileInfo\\Translation", &lpStr1, &dwLength);
    if(nRet){
      wTmp = (WORD*)lpStr1;

      //バージョン情報を取得する
      sTmp.sprintf("\\StringFileInfo\\%04x%04x\\FileVersion", *wTmp, *(wTmp + 1));
      nRet = VerQueryValue(pVersionInfo, sTmp.c_str(), &lpStr2, &dwLength);

      if(nRet) Result = (char*)lpStr2;
      else Result = "-";
    } else {
      Result="-";
    }
  } else {
    Result="-";
  }
  delete[] pVersionInfo;

  return Result;
}

[BCB] MDIで親フォームにスクロールバーを出さない方法

//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
    : TForm(Owner)
{
 FClientWndProc = MakeObjectInstance(ClientWndProc);
 if (FClientWndProc != NULL)
  FOrgWndProc = (void *)SetWindowLong(ClientHandle, GWL_WNDPROC,Longint(FClientWndProc));
}
//---------------------------------------------------------------------------
__fastcall TMainForm::~TMainForm(void)
{
 if (FOrgWndProc != NULL)
  SetWindowLong(ClientHandle, GWL_WNDPROC, Longint(FOrgWndProc));
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ClientWndProc(TMessage &Msg)
{
 switch (Msg.Msg) {
 case WM_NCCALCSIZE:
  // スクロールバーを消す
  ShowScrollBar(ClientHandle, SB_BOTH, false);
  Msg.Result = CallWindowProc((FARPROC)FOrgWndProc, ClientHandle,Msg.Msg, Msg.WParam, Msg.LParam);
  break;
 default:
  Msg.Result = CallWindowProc((FARPROC)FOrgWndProc, ClientHandle,Msg.Msg, Msg.WParam, Msg.LParam);
  break;
 }
}

[BCB] 最大化したときのFormのサイズを取得する方法

ヘッダ
class TMainForm : public TForm
{
  :
private:
 TRect FMaximizedRect;
 // メッセージハンドラ
 void _fastcall WMGetMinMaxInfo(TWMGetMinMaxInfo &Msg);

 BEGIN_MESSAGE_MAP
 MESSAGE_HANDLER(WM_GETMINMAXINFO, TWMGetMinMaxInfo, WMGetMinMaxInfo)
 END_MESSAGE_MAP(TForm)
  :
};


ソース
void _fastcall TMainForm::WMGetMinMaxInfo(TWMGetMinMaxInfo &Msg)
{
 //最大化したときのFormのサイズを取得
 FMaximizedRect.Top=0;
 FMaximizedRect.Left=0;
 FMaximizedRect.Right=Msg.MinMaxInfo->ptMaxSize.x;
 FMaximizedRect.Bottom=Msg.MinMaxInfo->ptMaxSize.y;

 /* その他、取得できる値
  //最大化の時のポジション
  Msg.MinMaxInfo.ptMaxPosition.x , Msg.MinMaxInfo.ptMaxPosition.y
  //最小サイズ
  Msg.MinMaxInfo.ptMinTrackSize.x , Msg.MinMaxInfo.ptMinTrackSize.y
  //最大サイズ
  Msg.MinMaxInfo.ptMaxTrackSize.x , Msg.MinMaxInfo.ptMaxTrackSize.y
 */
}

設定値を取得するだけでなく、逆に値を設定することもできるので最大化したときのサイズを変えたりもできる。

« 2005年1月 | トップページ | 2006年1月 »