[C++Builder] ファイル名がワイルドカードにマッチしているかを調べる

#include <Masks.hpp>

MatchesMask

|

[C++Builder] SIMD

#include <nmmintrin.h>   // MMX-SSE4.2
#include <smmintrin.h>   // MMX-SSE4.1
#include <intrin.h>      // MMX-SSE3
#include <emmintrin.h>   // MMX-SSE2
#include <xmmintrin.h>   // MMX-SSE
#include <mmintrin.h>    // MMX

 

|

[C++Builder] PNGを読み込むと未解決の外部参照 'Pnglang'

C++ Builder 2009でTImageにPNG画像を読み込んでコンパイルすると以下のエラーがでる。TPNGImageを直接利用しても同様のエラー。

[ILINK32 エラー] Error: 未解決の外部参照 'Pnglang::_EPngInvalidCRCText' が C:\PROGRAM FILES\CODEGEAR\RAD STUDIO\6.0\LIB\OBJ\PNGIMAGE.OBJ から参 照されました

画像処理のパッケージがVCLJPGからVCLIMGに変更されたことが原因。
プロジェクトにPnglang.hppを追加するか(Program Files以下で検索すれば見つかる)、PNGImage.hppの適当なところに

#pragma link "vclimg.lib"

を書いておけば大丈夫

|

[C++Builder] AnsiStringでコードページを指定する

C++Builder 2009ではAnsiStringでコードページが指定できます。

typedef AnsiStringT<932> SJISString;

|

[C++Builder] 警告を表示しないようにする

//非表示にする
#pragma warn -8056

//表示するようにする
#pragma warn .8056

VCの
#pragma warning(disable : 8056)
#pragma warning(default : 8056)
に対応

|

[BCB] 「すべてはい」「すべていいえ」がついたMessageBox

   TForm *Dlg=CreateMessageDialog("元のファイルが上書きされます。続行し
てもよろしいですか?",mtWarning,TMsgDlgButtons() <<mbOk<<mbNoToAll<<mbYesToAll<<mbCancel);
  Dlg->Caption="警告";
  Dlg->ShowModal();
  delete Dlg;

TMsgDlgBtn値、戻り値
mbOK、mrOk
mbCancel、mrCancel
mbYes、mrYes
mbNo、mrNo
mbAbort、mrAbort
mbRetry、mrRetry
mbIgnore、mrIgnore
mbAll、mrAll
mbNoToAll、mrNoToAll
mbYesToAll、mrYesToAll

|

[BCB] dfmファイルを使わずにFormを作成する

TFormのCreateNewメソッドを使います。普通にnewするとリソースが見つからない、とエラーになります。

|

[BCB] MessageBoxでデフォルトのボタンを指定する

デフォルトボタンを指定するには、以下のいずれかの値を使います。何も指定しなかった場合には、最初のボタンがデフォルトになります。

0x00000000 (MB_DEFBUTTON1)
最初のボタンをデフォルトにする
0x00000100 (MB_DEFBUTTON2)
2番目のボタンをデフォルトにする
0x00000200 (MB_DEFBUTTON3)
3番目のボタンをデフォルトにする
0x00000300 (MB_DEFBUTTON4)
4番目のボタンをデフォルトにする

例:
Application->MessageBoxA("続行しますか ?","確認",MB_OKCANCEL|MB_DEFBUTTON2);

|

[BCB] エクスプローラからのドラッグ & ドロップに対応する

//ヘッダファイル
class TForm1 : public TForm
{
    :

private:
    //実際にメッセージを処理する関数の宣言
    //関数の中身はソースに自分で書く
    void __fastcall WMDropFile(TWMDropFiles &Msg);

BEGIN_MESSAGE_MAP
    //捕まえたいメッセージと、それを処理する関数を登録
    VCL_MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WMDropFile)
END_MESSAGE_MAP(TComponent)

};

//ソースファイル

void __fastcall TForm1::FormCreate(TObject *Sender)
begin
  DragAcceptFiles(Handle, true);
end;

void __fastcall TForm1::WMDropFile(TWMDropFiles &Msg)
{
  //ドロップされたファイルを取得
  int Count=DragQueryFile((void *)Msg.Drop, -1, NULL, 0);
  for (int i=0;i<Count;i++) {
    char Filename[MAX_PATH]={0};
    DragQueryFile((void *)Msg.Drop, i, Filename, MAX_PATH);
      
    //Filenameを処理
  }
  DragFinish((void *)Msg.Drop);
}

|

[BCB] アラインメントの設定

#pragma pack(push,1)
struct TAPP1Header {
  WORD Maker;
  WORD Size;
  byte Magic[6];
};
#pragma pack(pop)

|

[BCB/Delphi] 再描画に関するメソッド

再描画に関連するメソッド

・Invalidate
  再描画が必要であることを宣言します。実際の再描画は適当なタイミングで実施されます。

・Update
  Invalidateなどで保留中の再描画を強制的に実施します。

・Repaint
  Invalidateを呼び出した後、Updateを呼び出します。強制的に再描画します。

・Refresh
  Repaintと同じです。

|

[BCB] TColorからR,G,B値への変換

赤(R)、緑(G)、青(B)を取得するには、それぞれGetRValue、GetGValue、GetBValueを使う。

(例)
byte R=GetRValue(clBlue);

|

[BCB,Delphi] RGBとHLSの変換

#include <GraphUtil.hpp>

void __fastcall ColorRGBToHLS(unsigned clrRGB, Word &Hue, Word &Luminance, Word &Saturation);

unsigned __fastcall ColorHLSToRGB(Word Hue, Word Luminance, Word Saturation);

|

[BCB] 数値入力専用のTEdit

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender) {
  SetWindowLong(Edit1->Handle, GWL_STYLE, GetWindowLong(Edit1->Handle, GWL_STYLE)|ES_NUMBER);
}

さらに、ES_RIGHTを追加すれば右寄せになります。

|

[BCB] 関数のtypedef

typedef int (__stdcall *TMyFunc)(int Param1,int Param2);

|

[BCB] DLLを動的に読み込む

HMODULE LoadLibrary(LPCTSTR lpFileName);

FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName);

BOOL FreeLibrary(HMODULE hModule);

|

[BCB] マウスの押下中だけカーソルを変更する

MouseDownイベントでVCLのCursorプロパティを変更しても、マウスのボタンが開放されるまでカーソルが変更されません。ボタンが押された瞬間に変更するにはWindows APIを使います。

::SetCursor(Screen->Cursors[crHourGlass]);

またMouseUpイベントにはカーソルを元に戻すコードを書きます。こちらは、VCLのCursorプロパティでもOKです。

Image1->Cursor=ceDefault;

|

[BCB] 独自のマウスカーソルを使う

----------------
1.まずカーソルデータが含まれたリソースファイルを作成 (参考:独自のリソースを使う

mycursor.rc

MyCursor1 CURSOR "Cursor_1.cur"
MyCursor2 CURSOR "Cursor_2.cur"

このファイルをプロジェクトに追加する。

----------------
2.メインフォームのOnCreateでリソースからカーソルを読み込む

//カーソル定数
static const TCursor crMyCursor1=1;
static const TCursor crMyCursor2=2;

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  Screen->Cursors[crMyCursor1] = LoadCursor(HInstance, "MyCursor1");
  Screen->Cursors[crMyCursor2] = LoadCursor(HInstance, "MyCursor2");
}

カーソル定数はデフォルトの定数(crDefaultなど)と重ならないように定義する。カーソル定数はTCursor型で-32768から32367までの整数であり、BDS2006では-22から0までがデフォルトの定数に使用されている。

注意:カーソルを使い終わってもDestroyCursorを呼び出してはいけない。勝手に開放される。

----------------
3.使いたいことろで、

Image1->Cursor=crMyCursor1;

のように使う。

----------------

|

[BCB] スクリーンセーバが起動しないようにする

WM_SYSCOMMAND の wParamがSC_SCREENSAVE のとき1を返せばスクリーンセーバの起動を抑制できるようです。

ヘッダ

private:
  void __fastcall WMSysCommand(TMessage &Msg);

  BEGIN_MESSAGE_MAP
    //捕まえたいメッセージと、それを処理する関数を登録
    VCL_MESSAGE_HANDLER(WM_SYSCOMMAND, TMessage, WMSysCommand)
  END_MESSAGE_MAP(TComponent)

ソース

//---------------------------------------------------------------------------
//スクリーンセーバの起動を抑制
void __fastcall TForm1::WMSysCommand(TMessage &Msg)
{
  if (Msg.WParam==SC_SCREENSAVE) {
    Msg.Result=1;
  } else {
    Msg.Result=DefWindowProc(Handle,Msg.Msg,Msg.WParam,Msg.LParam);
  }
}

|

[BCB] 書式付き文字列関数、 FormatのBCB版

AnsiString __cdecl FormatEx(const char *format, ...)
{
  va_list args;

  va_start(args,format);

  AnsiString Buf="";
  Buf.vprintf(format,args);
  va_end(args);

  return Buf;
}

使い方は、

AnsiString Str=FormatEx("%sは%dです",buffer,i);

|

[BCB] 空ではないフォルダを削除する関数

RemoveDir関数は空でないフォルダを削除することができません。空ではないフォルダを削除するにはSHFileOperationを使う方法もありますが、ここでは再帰的に削除する方法を示します。

bool __fastcall TForm1::ForceRemoveDir(AnsiString DirName)
{
  TSearchRec sr;
  int Attr=faAnyFile;
  bool Result=true;

  DirName=IncludeTrailingPathDelimiter(DirName);
  if (FindFirst(DirName+"*",Attr,sr)==0) {
    do {
      if ((sr.Name==".")||(sr.Name=="..")) continue;

      if ((sr.Attr&faDirectory)!=0)
        Result=Result && ForceRemoveDir(DirName+sr.Name);
      else
        Result=Result && DeleteFile(DirName+sr.Name);
    } while (FindNext(sr)==0);
    FindClose(sr);
  }
  Result=Result && RemoveDir(ExcludeTrailingPathDelimiter(DirName));
  return Result;
}

|

[BCB] 文字列に含まれる環境変数を展開する

文字列に含まれる%SystemRoot%のような環境変数を展開する方法です。

ExpandEnvironmentString関数を使います。

  char ExpandName[MAX_PATH];
  ExpandEnvironmentStrings("%SystemRoot%\temp",ExpandName,sizeof(ExpandName));

|

[BCB] OnAdvancedCustomDrawSubItem, OnAdvancedCustomDrawItemでフォントがおかしくなる

TListViewのOnAdvancedCustomDrawSubItemやOnAdvancedCustomDrawItemイベントで処理をするとフォントがおかしくなることがあります。

その場合は、以下を書き加えてみてください。

    if (ListView1->Canvas->Font->OnChange!=NULL) ListView1->Canvas->Font->OnChange(ListView1->Canvas->Font);

|

[BCB] システムフォルダを取得する

デスクトップやマイドキュメントなどの特殊フォルダの位置を取得する方法です。
以下はデスクトップの位置を取得する例です。

#include <shlobj.h>


  TCHAR szPath[_MAX_PATH];
  LPITEMIDLIST pidl;

  IMalloc *pMalloc;
  SHGetMalloc(&pMalloc);

  if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, &pidl))) {
    SHGetPathFromIDList(pidl,szPath);
    pMalloc->Free(pidl);             
  }
  pMalloc->Release();

|

[BCB] タイトルバーがないフォームを移動する

//Header file
class TForm1 : public TForm
{
__published: // IDE 管理のコンポーネント
private: // ユーザー宣言
  void __fastcall WMNCHitTest(TWMNCHitTest &Msg);

BEGIN_MESSAGE_MAP
  VCL_MESSAGE_HANDLER(WM_NCHITTEST, TWMNCHitTest, WMNCHitTest)
END_MESSAGE_MAP(TComponent)
public:  // ユーザー宣言
  __fastcall TForm1(TComponent* Owner);
};


//cpp file
void __fastcall TForm1::WMNCHitTest(TWMNCHitTest &Msg)
{
  DefaultHandler(&Msg);

  if (Msg.Result==HTCLIENT) {  // クライアント領域がクリックされら
    Msg.Result = HTCAPTION;    //タイトルバーがクリックされたと Windows に思わせる
  }
}

|

[BCB] 継承元の'Label2'が見つかりません. エラー

プロジェクトをコンパイルしようとしたところ「継承元の'Label2'が見つかりません.」というダイアログが表示され、コンパイルが出来なくなってしまいました。

調べてみたところ、IDEのバグのようでホームページ上で対処法が公開されていました。

http://support.codegear.com/jp/print/35919

対処法としては、プロジェクトファイルをエディタなどで開いて、次の2つのエレメントを削除した後、開きなおしたところコンパイル出来るようになりました。

<property category="build.node" name="libraries" value="..."/>
<property category="build.node" name="sparelibs" value="..."/>

詳細は、CodeGearのホームページをご覧ください。

|

[BCB] shlobj.hをincludeするとコンパイルエラー

#include <shlobj.h>

すると

FOLDERSETTINGSの宣言が複数見つかった
DESKBANDINFOの宣言が複数見つかった
 :

というエラーがでます。

解決するには、「プロジェクト」-「オプション」から「パスと定義」の条件定義にNO_WIN32_LEAN_AND_MEANを追加します(BDS2006の場合)。

ソースの中で
#define NO_WIN32_LEAN_AND_MEAN
してもうまくいきませんでした。

|

[BCB] 実行時にTActionを作成する

ActionListは設計時にForm上に配置されているものとします。

TAction *Action=new TAction(ActionList1); //TActionを作る
Action->ActionList=ActionList1; //ActionListを設定する

|

[BCB] マウスカーソルを消す/表示する

//消す
do { } while (ShowCursor(FALSE)<0);

//表示する
do { } while (ShowCursor(TRUE)>=0);

|

[BCB] FILETIMEをTDateTimeに変換

// TFileTime型をTDateTime型に変換する
TDateTime __fastcall TForm1::FileTimeToDateTime(TFileTime FileTime)
{
  TFileTime LocalTime;
  TSystemTime SystemTime;

  if ((FileTime.dwLowDateTime==0) && (FileTime.dwHighDateTime==0)) return 0;

  FileTimeToLocalFileTime(&FileTime,&LocalTime);
  FileTimeToSystemTime(&LocalTime,&SystemTime);
  return SystemTimeToDateTime(SystemTime);
}

|

[BCB] 現在のOSの言語名を取得する

  char *LangName=NULL;

  LCID id=GetUserDefaultLCID();
  int Len=GetLocaleInfo(id,LOCALE_SENGLANGUAGE,NULL,0);
  if (Len>0) {
    LangName=new char[Len+1];
    ZeroMemory(LangName,Len+1);
    GetLocaleInfo(id,LOCALE_SENGLANGUAGE,LangName,Len+1);
  }

LOCALE_SENGLANGUAGEの部分を変えれば、国名(LOCALE_SENGCOUNTRY)や通貨名(LOCALE_SENGCURRNAME)、日付時刻の区切り文字(LOCALE_SDATE、LOCALE_STIME)などの各種ロケール情報を取得できます。

|

[BCB] OSの言語を判定

LCID LocaleID=GetUserDefaultLCID();

switch (LocaleID) {
case 1025: //Arabic (Saudi Arabia)
case 2049: //Arabic (Iraq)
case 3073: //Arabic (Egypt)
case 4097: //Arabic (Libya)
case 5121: //Arabic (Algeria)
case 6145: //Arabic (Morocco)
case 7169: //Arabic (Tunisia)
case 8193: //Arabic (Oman)
case 9217: //Arabic (Yemen)
case 10241: //Arabic (Syria)
case 11265: //Arabic (Jordan)
case 12289: //Arabic (Lebanon)
case 13313: //Arabic (Kuwait)
case 14337: //Arabic (U.A.E.)
case 15361: //Arabic (Bahrain)
case 16385: //Arabic (Qatar)
case 1026: //Bulgarian
case 1027: //Catalan
case 1028: //Chinese (Taiwan)
case 2052: //Chinese (PRC)
case 3076: //Chinese (Hong Kong)
case 4100: //Chinese (Singapore)
case 1029: //Czech
case 1030: //Danish
case 1031: //German (Standard)
case 2055: //German (Swiss)
case 3079: //German (Austrian)
case 4103: //German (Luxembourg)
case 5127: //German (Liechtenstein)
case 1032: //Greek
case 1033: //English (United States)
case 2057: //English (United Kingdom)
case 3081: //English (Australian)
case 4105: //English (Canadian)
case 5129: //English (New Zealand)
case 6153: //English (Ireland)
case 7177: //English (South Africa)
case 8201: //English (Jamaica)
case 9225: //English (Caribbean)
case 10249: //English (Belize)
case 11273: //English (Trinidad)
case 1034: //Spanish (Traditional Sort)
case 2058: //Spanish (Mexican)
case 3082: //Spanish (Modern Sort)
case 4106: //Spanish (Guatemala)
case 5130: //Spanish (Costa Rica)
case 6154: //Spanish (Panama)
case 7178: //Spanish (Dominican Republic)
case 8202: //Spanish (Venezuela)
case 9226: //Spanish (Colombia)
case 10250: //Spanish (Peru)
case 11274: //Spanish (Argentina)
case 12298: //Spanish (Ecuador)
case 13322: //Spanish (Chile)
case 14346: //Spanish (Uruguay)
case 15370: //Spanish (Paraguay)
case 16394: //Spanish (Bolivia)
case 17418: //Spanish (El Salvador)
case 18442: //Spanish (Honduras)
case 19466: //Spanish (Nicaragua)
case 20490: //Spanish (Puerto Rico)
case 1035: //Finnish
case 1036: //French (Standard)
case 2060: //French (Belgian)
case 3084: //French (Canadian)
case 4108: //French (Swiss)
case 5132: //French (Luxembourg)
case 1037: //Hebrew
case 1038: //Hungarian
case 1039: //Icelandic
case 1040: //Italian (Standard)
case 2064: //Italian (Swiss)
case 1041: //Japanese
case 1042: //Korean
case 2066: //Korean (Johab)
case 1043: //Dutch (Standard)
case 2067: //Dutch (Belgian)
case 1044: //Norwegian (Bokmal)
case 2068: //Norwegian (Nynorsk)
case 1045: //Polish
case 1046: //Portuguese (Brazil)
case 2070: //Portuguese (Portugal)
case 1048: //Romanian
case 1049: //Russian
case 1050: //Croatian
case 2074: //Serbian (Latin)
case 3098: //Serbian (Cyrillic)
case 1051: //Slovak
case 1052: //Albanian
case 1053: //Swedish
case 2077: //Swedish (Finland)
case 1054: //Thai
case 1055: //Turkish
case 1057: //Indonesian
case 1058: //Ukrainian
case 1059: //Belarusian
case 1060: //Slovenian
case 1061: //Estonian
case 1062: //Latvian
case 1063: //Lithuanian
case 1065: //Farsi
case 1066: //Vietnamese
case 1069: //Basque
case :1078 //Afrikaans
case 1080: //Faeroese
}

|

[BCB] FileCtrl.hppでリンクエラー

#include<FileCtrl.hpp> して

MinimizeNameやSelectDirectoryなどを使おうとすると、コンパイル時にリンクエラー、未解決の外部参照となる場合があります。原因はよくわかりませんが、vclx.lib(BDS2006の場合、それ以外の場合はお尻に数字がつく)というファイルをインストールしたディレクトリ以下から探してきて、プロジェクトに追加してやればコンパイルが通るようになります。

|

[BCB] LOGFONTとTFontの変換

LOGFONT lf;

//TFont -> LOGFONT
GetObject(Canvas->Font->Handle, sizeof(LOGFONT), &lf);

//LOGFONT -> TFont
Canvas->Font->Handle = CreateFontIndirect(&lf);

|

[BCB] ListViewで選択中の行までスクロール

if (ListView1->Selected!=NULL)
  ListView1->Selected->MakeVisible(true);

|

[BCB] ウインドウを列挙する

//-----------------------------------------------------
void __fastcall ListupWindows(void)
{
  //ウインドウの列挙
   EnumWindows((WNDENUMPROC)EnumWindowsProc , NULL);
}

//------------------------------------------------------
BOOL CALLBACK EnumWindowsProc(HWND hwnd , LPARAM lp)
{
  if ((GetWindow(hwnd,GW_OWNER)==NULL) && (IsWindowVisible(hwnd))) {
    char buf[1024];
    ZeroMemory(buf,1024);
    GetWindowModuleFileName(hwnd,buf,1024);
    /*
    GetWindowText(hwnd , buf , 1024);
    GetClassName(hwnd , buf , 1024);
    DWORD processID=0;
    GetWindowThreadProcessId(hwnd, &processID);
    */
   
    Form1->ListBox1->Items->Add(Str);
  } 
  return TRUE;
}

|

[BCB] プロセスを列挙する

#include <Tlhelp32.h>

void EnumProcesses()
{
  //プロセスの列挙   
  HANDLE hSnapShot;
   PROCESSENTRY32 procEntry;

   //システムのスナップショットを取得
   hSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
   procEntry.dwSize =sizeof(procEntry);
   if (Process32First (hSnapShot,&procEntry)!=NULL) {
    do {
       ListBox1->Items->Add(procEntry.szExeFile);
     } while (Process32Next (hSnapShot,&procEntry));
   }
   CloseHandle(hSnapShot);
}

|

[BCB] ListViewのHeader(Column)に画像を表示する

ListViewのヘッダーに画像を表示する方法です。文字列の左側に表示する場合はプロパティを設定するだけで簡単にできますが、文字列の右側に画像を表示する場合は以下の関数で実現できます。表示したい画像はあらかじめImageListにいれておきます。

void __fastcall TForm1::ShowImageToLvColumn(TListView *ListView,int ACol,int ImageIndex)
{
  //ヘッダコントロールのハンドル取得
  HWND ColumnHandle=ListView_GetHeader(ListView->Handle);
  if (ColumnHandle==NULL) return;
  //イメージリストを割り当て
  if (!Header_SetImageList(ColumnHandle,ImageList1->Handle)) return;

  //設定を取得
  HD_ITEM hi;
  hi.mask=HDI_FORMAT;
  if (!Header_GetItem(ColumnHandle,ACol,&hi)) return;

  //イメージを設定
  hi.mask   = HDI_IMAGE|HDI_FORMAT;
  if (ImageIndex>=0) {
    hi.fmt   |= HDF_IMAGE|HDF_BITMAP_ON_RIGHT;  // 取得しておいたフォーマットに HDF_IMAGE 追加
    hi.iImage = ImageIndex; // ImageListのID
  } else {
    hi.fmt   &= ~(HDF_IMAGE|HDF_BITMAP_ON_RIGHT);
    hi.iImage = 0; //-1をいれるとエラーになる
  }
  Header_SetItem(ColumnHandle,ACol,&hi);
}

|

[Delphi,BCB] アイコンリソースを追加したらアプリのアイコンが変わった!

rcファイルを使ってアイコンリソースをEXEファイルに埋め込んだときに、アプリケーションのメインアイコンが変わってしまうことがあります。これは、Delphi,BCBはリソース名でリソースを並び替えてしまうためにおきる問題です。

解決策としては、Delphi,BCBではメインアイコンをMAINICONの名前で保持していますので、ソートした時に、これよりも後に来るような名前を付けます。例えば、

OREICON  ICON  "aaa.ico"

のような感じです。MよりもOの方がアルファベット順が後になります。

|

[BCB] HTTP Encode

AnsiString __fastcall HTTPEncodeUTF8(const AnsiString AStr)
{
  WideString WStr=AStr;
  UTF8String UStr=UTF8Encode(AStr);

  AnsiString Result="";
  for (int i=1;i<=UStr.Length();i++) {
    byte Ch=UStr[i];
    if ((Ch>='A' && Ch<='Z') ||
        (Ch>='a' && Ch<='z') ||
        (Ch=='*') ||
        (Ch=='@') ||
        (Ch=='.') ||
        (Ch=='_') ||
        (Ch=='-')) {
      Result=Result+(char)Ch;
    } else if (Ch==' ') {
      Result=Result+"+";
    } else {
      Result=Result+"%"+AnsiString().sprintf("%.2X",Ch);
    }
  }
  return Result;
}

|

[Delphi] ListViewのHeaderに画像を表示する

ListViewのHeaderにソートの方向を表す矢印(三角マーク)を表示したりするときに、役に立つと思います。

TreeViewEx1.ColumnImages[2]:=0;

のように設定すると2列目のヘッダにSmallImageに設定されているImageListの最初の画像が表示されます。消すときはColumnImages[2]:=-1のようにします。

|

[BCB] CheckBox付きのMessageDialog

TModalResult CheckMessageDialog(AnsiString Message, AnsiString Caption,
  AnsiString CheckBoxCaption, bool &Checked,
  TMsgDlgType DlgType, TMsgDlgButtons Buttons)
{
   TForm *Dialog=CreateMessageDialog(Message, DlgType, Buttons);
   if (!Caption.IsEmpty()) Dialog->Caption = Caption;

   int LeftEdge=Dialog->ClientWidth;
   int TopEdge =Dialog->ClientHeight;
   if (Dialog->ControlCount>0) {
     for (int i = 1; i < Dialog->ControlCount; i++) {
       TControl *Ctrl=Dialog->Controls[i];
       if (Ctrl->Left < LeftEdge) LeftEdge=Ctrl->Left;
       if (Ctrl->Top  < TopEdge)  TopEdge =Ctrl->Top;
     }
   } else {
     LeftEdge=20;
     TopEdge=20;
   }

   TCheckBox * CheckBox = new TCheckBox(Dialog);
   CheckBox->Parent  = Dialog;
   CheckBox->Caption = CheckBoxCaption;
   CheckBox->Checked = Checked;
   CheckBox->Left    = LeftEdge;
   CheckBox->Top     = Dialog->ClientHeight;
   CheckBox->Width   = Dialog->Canvas->TextWidth(CheckBox->Caption)+30;

   Dialog->ClientHeight = Dialog->ClientHeight + CheckBox->Height + TopEdge;

   if (CheckBox->Width + LeftEdge*2 > Dialog->ClientWidth)
     Dialog->ClientWidth = CheckBox->Width + LeftEdge*2;

   TModalResult Result = Dialog->ShowModal();
   Checked = CheckBox->Checked;

   delete Dialog;
   Dialog=NULL;
   
   return Result;
}

使い方
  bool Checked=false;
   CheckMessageDialog("本当に削除してもよろしいですか ?\r\nC:\\tmp\\*.*",
      "確認","今後は確認しない", Checked,
      mtConfirmation, (TMsgDlgButtons() << mbYes << mbNo << mbHelp));

|

[BCB] ListViewで行毎に背景色を変える

void __fastcall TForm1::ListView1AdvancedCustomDrawItem(
      TCustomListView *Sender, TListItem *Item, TCustomDrawState State,
      TCustomDrawStage Stage, bool &DefaultDraw)
{
  if (Item->Index%2==0)
    Sender->Canvas->Brush->Color=(TColor)RGB(240,240,255);
}

|

[BCB] 右寄せのTStatusBar

//header file
class TForm1 : public TForm
{
   :
private: // ユーザー宣言
        int *FStatusBarWidths;
   :
};

//cpp file
//

|

[BCB] 中間ファイルを使用せずにWebBrowserに直接書き込む

Delphiでは割と簡単だったのですが。もっと簡単な方法があるのでしょうか?


  AnsiString Str="<html>aaaa</html>";

  SAFEARRAY *safe_array = SafeArrayCreateVector(VT_VARIANT,0,1);
  VARIANT *variant;

  SafeArrayAccessData(safe_array,(void **)&variant);
  variant->vt      = VT_BSTR;            
  variant->bstrVal = SysAllocString(WideString(Str));
  SafeArrayUnaccessData(safe_array);

  IHTMLDocument2 *Html=NULL;
  CppWebBrowser1->Navigate(L"about:blank");
  CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2,(void **)&Html);
  Html->write(safe_array);

  Html->close();
  Html->Release();

  SafeArrayDestroy(safe_array);

|

[BCB] バイナリサーチ(2分探索)

int __fastcall TSortedObjectList::BinSearch(int Key)
{
  if (FList->Count==0)  return -1;

  int LeftIdx=0;
  int RightIdx=FList->Count-1;

  while (LeftIdx<=RightIdx) {
    int MidIdx=(LeftIdx+RightIdx)/2;
    int MidVal=(int)FList->Items[MidIdx];
    if (MidVal==Key) return MidIdx;  //見つかった
    else if (Key>MidVal) LeftIdx=MidIdx+1;
    else RightIdx=MidIdx-1;
  }

   return -1;
}

| | コメント (0)

[BCB] Enterキーで次のコントロールにフォーカスを移動する

void __fastcall TForm1::Edit1KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
  if (Key==VK_RETURN) {
    SendMessage(Handle, WM_NEXTDLGCTL, 0, 0);
    Key=0x00;
  }
}

|

[Delphi,BCB] StrToIntで例外が発生するのがめんどくさい

StrToIntは文字列を数字に変換するための関数ですが、引数に数字として不正な文字列(例えば「125a」とか)を渡すと例外が発生してしまいます。これをきちんと処理するのが面倒だったり、単純に不正な文字列が渡された場合は-1を返してほしいと思う場合があったりします。そういう時に便利なのがStrToIntDefという関数です。

i:=StrToIntDef(Edit1.Text,-1);

というようにデフォルト値を指定して変換ができます。変換に失敗した場合はデフォルト値が返される仕組みです。例外は発生しません。場合によっては非常に便利な関数です。

|

[BCB] ファイルのタイムスタンプ(更新日時など)を取得

ファイルの「作成日時」「更新日時」「アクセス日時」を取得する方法です。手順は
1.ファイルをオープン (CreateFile)
2.ファイルタイムを取得 (GetFileTime)
3.取得したファイルタイム(UTC)をローカルタイムに変換 (FileTimeToLocalFileTime)
4.ローカルファイルタイムをシステムタイムに変換 (FileTimeToSystemTime)
5.システムタイムをTDateTime型に変換 (SystemTimeToDateTime)
6.ファイルをクローズ (CloseHandle)
となります。

  HANDLE hFile;
  FILETIME FtCreationTime,FtLastAccessTime,FtLastWriteTime;
  FILETIME LftCreationTime,LftLastAccessTime,LftLastWriteTime;
  SYSTEMTIME StCreationTime,StLastAccessTime,StLastWriteTime;

  hFile = CreateFile(Filename.c_str() , GENERIC_READ , 0 , NULL ,
  OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL);
  if (hFile != INVALID_HANDLE_VALUE) {
    GetFileTime(hFile,&FtCreationTime,&FtLastAccessTime,&FtLastWriteTime);

    FileTimeToLocalFileTime(&FtCreationTime,&LftCreationTime);
    FileTimeToSystemTime(&LftCreationTime ,&StCreationTime);
    Edit1->Text=FormatDateTime("yyyy/mm/dd hh:nn:ss",SystemTimeToDateTime(StCreationTime));

    FileTimeToLocalFileTime(&FtLastAccessTime ,&LftLastAccessTime);
    FileTimeToSystemTime(&LftLastAccessTime ,&StLastAccessTime);
    Edit2->Text=FormatDateTime("yyyy/mm/dd hh:nn:ss",SystemTimeToDateTime(StLastAccessTime));

    FileTimeToLocalFileTime(&FtLastWriteTime ,&LftLastWriteTime);
    FileTimeToSystemTime(&LftLastWriteTime ,&StLastWriteTime);
    Edit3->Text=FormatDateTime("yyyy/mm/dd hh:nn:ss",SystemTimeToDateTime(StLastWriteTime));
  }
  CloseHandle(hFile);


関連項目:
 ・世界協定時刻(UTC)をローカルタイムに変換
 ・TSystemTime(_SYSTEMTIME)とTDateTimeの変換

|

[BCB] Formを半透明にする

Windows 2000以降でFormを半透明にする方法です。SetLayeredWindowAttributes関数の3番目の引数で透明度を指定します。0が完全に透明で255が不透明です。

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  SetWindowLong(Handle, GWL_EXSTYLE,GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
  SetLayeredWindowAttributes(Handle,0,200,LWA_ALPHA);
}

同じ関数を使って、ある色だけを透明にしたりもできます。以下の例は、Formの白色の部分を完全に透明にした上で、Formを半透明にしています。

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  SetWindowLong(Handle, GWL_EXSTYLE,GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
  SetLayeredWindowAttributes(Handle,clWhite,200,LWA_COLORKEY | LWA_ALPHA);

|

[Delphi/BCB] manifestファイルをexeに埋め込む

manifestファイルの書き方はこちらを参照してください。

作成したmanifestファイルをexeファイルにリソースとして埋め込む方法です。

#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define CONTROL_PANEL_RESOURCE_ID 123
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "○○.exe.manifest"

これをmanifest.rcというようなファイル名で保存します。なお上記の○○の部分には実行ファイルの名前を書きます。「プロジェクト」-「プロジェクトに追加」で作成したrcファイルをプロジェクトに追加します。

これでコンパイルすればOKです。

|

[BCB] セーフモードが通常モードかを判定する

switch (GetSystemMetrics(SM_CLEANBOOT)) {
case 0:
  //通常どおり起動された
  break;
case 1:
  //「Safeモード」で起動された
  break;
case 2:
  //「ネットワークを使ったSafeモード」で起動された
  break;
}

|

[BCB] マウスのボタンの数を取得する

int NumOfButton=GetSystemMetrics(SM_CMOUSEBUTTONS);

switch (NumOfButton) {
case 0:
  //マウスがない
  break;
case 1:
  //ボタンが1個
  break;
case 2:
    :

}

|

[BCB] マウスが接続されているか調べる

if (GetSystemMetrics(SM_MOUSEPRESENT)) {
  //接続されている
} else {
  //接続されていない
}

|

[BCB] ListViewに32bitアイコンを表示

BCB6.0では、ListViewなどにWindows XPで使用される32bitアイコン(アルファチャンネルを持つ半透明アイコン)を表示しようとすると、アルファがうまく反映されず、アイコンのふちが黒くなって表示されてしまいます。これを解決する方法です。

まず、ImageListを32bitに変更します。例えばFormCreateなどに次のようなコードを書いておきます。

void __fastcall TForm1::FormCreate(TObject *Sender)
{            
  UINT Flags=ILC_COLOR32;
  if (ImageList1->Masked) Flags|=ILC_MASK;
  ImageList1->Handle = (int)ImageList_Create(Width, Height, Flags, 0, ImageList1->AllocBy);
}

次に、manifestファイルを作成します。書き方はこちらを参照してください。
以上です。

BCB6.0、XP環境において、ImageListに32bitアイコンを追加していき、ListViewに表示したところ正常に表示されました。

|

[BCB] Windowsのシステムディレクトリを取得

「C:\Windows」のようなWindowsディレクトリを取得するには次のようにします。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  char Buf[MAX_PATH];
  GetWindowsDirectory(Buf,MAX_PATH);

   Label1->Caption=Buf;
}


同じように「C:\Windows\System32」のようなシステムディレクトリはGetSystemDirectoryで取得することができます。

|

[BCB] DLLのヘッダファイルの書き方

#ifndef HeaderH
#define HeaderH
//

|

[BCB] sprintfやDelphiのFormatのような関数は?

AnsiStringのsprintfメソッドを使います。
書式はDelphiのFormat関数と同じような感じです。

AnsiString Str=AnsiString().sprintf("%.5d",i);

|

[BCB] 書式付エラーダイアログ表示関数

printfのような書式付きのエラーダイアログ表示関数です。
使い方は

ShowError("Cannot open file %s",filename);

のような感じです。

#include <stdarg.h>

void __cdecl TForm1::ShowError(const char *format, ...)
{
  va_list args;

  va_start(args,format);

  AnsiString Buf="";
  Buf.vprintf(format,args);
  va_end(args);

  Application->MessageBoxA(Buf.c_str(),"ERROR",MB_OK | MB_ICONERROR);
}

|

[BCB] 時間を計測する

・GetTickCount
 コンピュータが起動してからの経過時間をミリ秒で返す。精度はいまいちで5~10ms程度。

・timeGetTime
 コンピュータが起動してからの経過時間をミリ秒で返す。

・QueryPerformanceCounter(LARGE_INTEGER *)
 高分解能パフォーマンスカウンタの値が取得できる。取得した値はQueryPerformanceFrequencyで得られるカウンタの周波数から、時間に変換できる。

  LONGLONG t1,t2,fr;

  QueryPerformanceFrequency((LARGE_INTEGER *)&fr);
  QueryPerformanceCounter((LARGE_INTEGER *)&t1);

  //計測したい処理

  QueryPerformanceCounter((LARGE_INTEGER *)&t2);
  Label1->Caption=AnsiString().sprintf("%.1f us", (double)(t2-t1) / fr * 1000000);

|

[BCB] 矢印キーやタブキーを捕まえる

class TForm1 : public TForm
{
  protected:
    void __fastcall CMDialogKey(Messages::TWMKey &Message)
    {
      if (Message.CharCode != VK_LEFT) TForm::Dispatch(&Message);
    }
BEGIN_MESSAGE_MAP
  MESSAGE_HANDLER(CM_DIALOGKEY, Messages::TWMKey, CMDialogKey);
END_MESSAGE_MAP(TForm)
};

|

[BCB] caseでローカル変数の初期化がとばされた?

switch文のcaseでローカル変数を以下のように使おうとすると、「caseでローカル変数の初期化がとばされた」というようなエラーメッセージが表示されてしまいます。

switch (Value) {
case 0:
  int i=0;
     :
  break;
default:
     :
  break;
}

このようなことをしたいときは時は次のようにcaseの中をブレースで括ります。

switch (Value) {
case 0:
  {
  int i=0;
     :
  break;
  }
default:
     :
  break;
}

| | コメント (0)

[BCB] EnumWindowsでコンパイルが通らない

ウインドウの一覧を得るEnumWindowsというAPIがありますが、C++Builder6.0でこの関数を使用すると以下のようなエラーがでる場合があるようです。

----
E2034 'int (__stdcall *)(void *,long)'型は'int (__stdcall *)()'型に変換できない
E2342 パラメータ 'EnumWndProc' は int (__stdcall *)() 型として定義されているので int (__stdcall *)(void *,long) は渡せない
----

以下のように強制的にキャストをかけてしまえばコンパイルできるようになります。きちんと意図した動作もしているようです。

//関数の定義
BOOL CALLBACK EnumWndProc(HWND hWindow,LPARAM lData)
{
   :
}

//呼び出し
EnumWindows((WNDENUMPROC)EnumWndProc,0);

| | コメント (0)

[BCB] アプリの2重起動を禁止する

Mutexを使用して、アプリケーションの2重起動を禁止する方法です。「プロジェクト」-「ソース表示」で表示されるファイルに以下のようなコードを追記します。

=====

#define MUTEX_ID "Unique_ID_String"  //適当な文字列を設定

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  try
  {

    HANDLE  hMutex=NULL;

    //2重起動のチェック

    //Mutexを作成してみる
    hMutex = CreateMutex(NULL, true, MUTEX_ID);
    if (hMutex!=NULL) {
      if (GetLastError()==ERROR_ALREADY_EXISTS) { //すでに起動されている
        CloseHandle(hMutex); // 閉じる
        ReleaseMutex(hMutex);// 破棄する

        //すでに起動済みの画面を探して前面に持ってくる処理などを書く

        return 0; //終了
      }
    } else {
      //Mutexの作成に失敗したときの処理
    }

    //この辺はもともと書かれている部分
    Application->Initialize();
       :
    Application->Run();

    //最後に後始末
    CloseHandle(hMutex); // 閉じる
    ReleaseMutex(hMutex); //ミューテクス解除
  }
  catch (Exception &exception)
  {
    Application->ShowException(&exception);
       :
  return 0;
}

| | コメント (0)

[BCB] Windowsのメッセージを処理する

BCBでWindowsのメッセージを捕まえて処理をする場合の書き方です。

class TForm1 : public TForm
{
    :

private:
    //実際にメッセージを処理する関数の宣言
    //関数の中身はソースに自分で書く
    void __fastcall WMDropFile(TWMDropFiles &Msg);


BEGIN_MESSAGE_MAP
    //捕まえたいメッセージと、それを処理する関数を登録
    VCL_MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WMDropFile)
END_MESSAGE_MAP(TComponent)

};

| | コメント (0)

[BCB] ディレクトリが存在するか調べる(Unicode版)

引数に指定されたディレクトリが存在するかを調べる関数です。ユニコードファイル名に対応しています。

bool __fastcall DirectoryExistsW(WideString WFilename)
{
  WIN32_FIND_DATAW FindFileData;
  HANDLE hFind;

  hFind = FindFirstFileW(WFilename.c_bstr(), &FindFileData);

  if (hFind != INVALID_HANDLE_VALUE) {
    // 検索ハンドルをクローズ
    FindClose(hFind);
    if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) return true;
  }
  return false;
}

| | コメント (0)

[BCB] ファイルが存在するか調べる(Unicode版)

引数に指定されたファイル名(ディレクトリも含む)が存在するかを調べる関数です。ユニコードファイル名に対応しています。

bool __fastcall FileExistsW(WideString WFilename)
{
  WIN32_FIND_DATAW FindFileData;
  HANDLE hFind;

  hFind = FindFirstFileW(WFilename.c_bstr(), &FindFileData);

  if (hFind != INVALID_HANDLE_VALUE) {
    // 検索ハンドルをクローズ
    FindClose(hFind);
    return true;
  }
  return false;
}

| | コメント (0)

[BCB] システムのフォントを取得

システムメニューやボタンなどで使用されるフォントを取得する方法です。以下は、システムのGUIで使用されるフォントを取得する例です。

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  HFONT hFont;
  TLogFont LogFont;
 
  hFont=GetStockObject(DEFAULT_GUI_FONT);
  GetObject(hFont,sizeof(LogFont),&LogFont);
}

DEFAULT_GUI_FONTの部分には、以下の値を指定することもできます。

  OEM_FIXED_FONT = 10;
  ANSI_FIXED_FONT = 11;
  ANSI_VAR_FONT = 12;
  SYSTEM_FONT = 13;
  DEVICE_DEFAULT_FONT = 14;
  DEFAULT_PALETTE = 15;
  SYSTEM_FIXED_FONT = 16;
  DEFAULT_GUI_FONT = 17;

| | コメント (0)

[BCB] コンポーネントの継承元(祖先)を判定する

Form上のコンポーネントのうち、ある特定のクラスから派生しているものだけに対して処理をしたい場合に使えるテクニックです。以下は、TControlから派生したクラスに対してのみ処理をする場合の例です。

  for (int i=0;i<ComponentCount;i++) {
    if (Components[i]->InheritsFrom(__classid(TControl))) {
      TControl *Ctrl=(TControl *)Components[i];
      
      //何か処理をする
    }
  }

| | コメント (0)

[BCB] デスクトップ作業領域の矩形を取得

TRect WorkAreaRect;

SystemParametersInfo( SPI_GETWORKAREA, 0, &WorkAreaRect, 0 );

| | コメント (0)

[Delphi/BCB] manifestファイルの書き方

manifestファイルを使うと、アプリケーションの外観を簡単にWindowsXPのスタイルにすることができます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
  version="1.0.0.0"
  processorArchitecture="X86"
  name="CompanyName.ProductName.YourApp"
  type="win32" />
<description>Description</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="X86"
            publicKeyToken="6595b64144ccf1df"
            language="*" />
    </dependentAssembly>
</dependency>
</assembly>

これを、○○.exe.manifestという名前のファイルに保存します。このとき文字コードはUTF-8にします。○○の部分は実行ファイルの名前を入れます。このファイルを実行ファイルと同じ場所においておけばOKです。

Delphi5の場合は、PageControlなど一部のコンポーネントは、うまくスタイルが変更されません。これらに対応したコンポーネントを作られている方もいるようです。

| | コメント (0)

[BCB] TrackBarの白い部分を消す

[ヘッダ]

class TMyTrackBar: public TTrackBar
{
public:
  __fastcall TMyTrackBar(TComponent* Owner);
  void __fastcall CreateParams(TCreateParams &Params);
};

[ソース]

//

| | コメント (0)

[BCB] HTML Helpを扱う

マイクロソフトのホームページからダウンロードできるHTML Help WorkshopにはプログラムからHTML Helpを扱うためのライブラリファイル(htmlhelp.lib)が付属していますが、BCBではそのまま使うことはできません。次のようにしてhhctrl.ocxからBCB用のライブラリファイルを作成します。

implib htmlhelp.lib hhctrl.ocx

BCBのプロジェクトに、作成したhtmlhelp.libと、Workshopに付属しているヘッダファイルhtmlhelp.hを追加します。

FormのOnCreateとOnCloseに下記のようなコードを書きます。

//

| | コメント (0)

[BCB] ListViewのコラムをクリックでソート

ListViewのコラムをクリックした時に、その列をキーに内容をソートする方法です。ListViewのViewStyleはvsReport、ShowColumnHeaderはtrueに設定されているとします。

クリックされた列の番号を保持しておく変数を用意しておきます。

  :
private
  int FColumnToSort;
  :
};

ListViewのOnColumnClickとOnCompareを使います。またTagプロパティは、コラムをクリックするたびに、ソートの方向(昇順か降順か)を反転するために使っています。

void __fastcall TForm1::ListView1ColumnClick(TObject *Sender,
      TListColumn *Column)
{
  FColumnToSort = Column->Index;
  ((TCustomListView *)Sender)->AlphaSort();

  //ソートの方向を切り替える 昇順、降順
  if (FColumnToSort==0)
    ListView1->Tag=(ListView1->Tag==1)?0:1;
  else
    ListView1->Columns->Items[FColumnToSort-1]->Tag=
      (ListView1->Columns->Items[FColumnToSort-1]->Tag==1)?0:1;
}
//

| | コメント (0)

[BCB] 相対パスと絶対パスの変換

相対パスから絶対パスへの変換はExpandFileName。
絶対パスから相対パスへの変換はExtractRelativePath。

これらの関数を使用する前には、SetCurrentDirでベースとなるディレクトリを設定する必要がある。

AnsiString AppDir=ExtractFilePath(Application->ExeName);
if (SetCurrentDir(AppDir)) {
  Label1->Caption=ExpandFileName("../../test.txt");
}

| | コメント (0)

[BCB] TSplitterでsnapされた状態で起動したい

TSplitterにおいてAutoSnapをTrueにすると、コンポーネントのサイズがMinSize以下となったときにサイズを0にしてくれます。このSnapされた状態で起動する方法です。

Panel1を見えない状態で起動する例です。

  Panel1->Height=1;
  Splitter1->Perform(WM_LBUTTONDOWN,0,0);
  Splitter1->Perform(WM_MOUSEMOVE,MK_LBUTTON|MK_MBUTTON,0);
  Splitter1->Perform(WM_LBUTTONUP,0,0);

| | コメント (0)

[BCB] BCB6.0のIndyをバージョンアップ

BCB6.0には最初からIndyがインストールされていますが、それをIndy9にバージョンアップする方法です。

最初にインストールを試みたときは、「プロシージャエントリポイント Idresourcestrings@_RSBindingAnyがダイナミックリンクライブラリIndy60.bplから見つかりませんでした。」というエラーがでてパッケージがインストールできず苦労しましたが、下記のとおりの順番でやり直したところうまくいきました。


前準備(BCBのアップデート)

(1) ボーランドのページからBorland C++Builder 6 アップデートパック #4をダウンロード。すでにインストール済みの場合はスキップ。

(2) アップデートパックをインストールする。

古いIndyのアンインストール

(3) コントロールパネルから「プログラムの追加と削除」を起動。

(4) その中から「Borland C++Builder 6」を選択して「変更」をクリック。インストールCDROMを求められた場合はCDROMを挿入。

(5) 表示された機能一覧の中から「Indy」を探して、「インストールしない」にして「次へ、次へ」。

(6) 残っているゴミの削除。以下はIndyのサイトに書いてあった情報。
 (6-1) $(BCB)フォルダ以下から「IDPAS32.obj」というファイルを検索していったん、デスクトップなどに移動する。BCB6.0なら $(BCB)\Source\vcl内に見つかると思います。
 (6-2) $(BCB)フォルダ以下から「dclindy*.bpl, dclindy.*, dclindy*.bpl, indy*.lib, id*.pas, id*.hpp, id*.obj, id*.dcu」を検索して削除。Indy関連ではないファイルを間違えて削除しないように注意。検索するときは「」内の文字列をそのままWindowsの検索画面の「ファイル名のすべてまたは一部」の欄に入力して検索すればOK。
 (6-2) C:\Windows\System32以下の「indy*.bpl」を検索して削除。
 (6-3) $(BCB)\Help以下から「indy.*」を検索して削除。
 (6-4) 6-1で移動しておいたIDPAS32.objを元の場所に戻す。

新しいIndyのダウンロードとインストール

(7) Indyのページからソースをダウンロード。WindowsはZipで配布されている。

(8) ダウンロードしてきたファイルを展開。展開して出てきたフォルダを、適当なフォルダを新規に作ってその中に移動する。

(9) 展開したフォルダの中にある「Fullc6.bat」を実行。DOSの画面が消えるまで待つ。実行が終わるとひとつ上のフォルダに「C6」というフォルダができている。

(10) 「C6」フォルダの中身を「$(BCB)\Source\Indy」にまるごとコピー。

(11) 「C6」フォルダの「dclIndy60.bpl」を「$(BCB)\bin」にコピー。

(12) 「C6」フォルダの「hpp」という拡張子のファイルを全部「$(BCB)\Include」にコピー。

(13) BCBを起動する。

(14) 「ツール」-「環境オプション」で表示されるダイアログで、「ライブラリ」タブを選択。「ライブラリパス」に「$(BCB)\Source\Indy」を追加して「OK」でダイアログを閉じる。

(15) 「コンポーネント」-「パッケージのインストール」。「追加」ボタンを押して「$(BCB)\bin\dclIndy60.bpl」を選択。チェックがついていることを確認して「OK」を押すとパレットに新しいIndyコンポーネントが追加される。

Indyヘルプファイルの更新

(16) Indyのページから新しいヘルプファイルをダウンロード。何種類が形式が用意されているが、元のと同じWinHelp形式を選択。

(17) ダウンロードしたファイルを展開。

(18) 展開したフォルダの中にあるファイルを丸ごと「$(BCB)\Help」にコピー。

インストールはこれで完了。

もともと古いバージョンのIndyを使っていたプロジェクトをコンパイルする場合は、そのままだとエラーが出る。プロジェクトファイル(例:Project1.bpr)をメモ帳などで開き、「Indy.lib」と「Indy.bpi」という文字列を検索して削除してから改めてコンパイルしなおすとうまくいく。

| | コメント (0)

[BCB] 電光掲示板のようにスクロールするラベル

電光掲示板の文字のようにスクロールするラベルです。 Form上にLabelとTimerをひとつずつ置きます。

スクロールさせたい文字列はCaptionStringという内部変数に入れておきます。TimerのIntervalは200くらいにしておきます。

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
 static int x=Label1->Width;
 RECT r;
 int w;

 r.left=0;
 r.top =0;
 r.right=Label1->Width;
 r.bottom=Label1->Height;

 w=Label1->Canvas->TextWidth(CaptionString);
 if (w+x<0) X=Label1->Width;

 Label1->Canvas->Brush->Color=Label1->Color;
 Label1->Canvas->Brush->Style=bsSolid;
 Label1->Canvas->FillRect(r);
 Label1->Canvas->TextRect(r,X,1,CaptionString);
 Label1->Update();
 x=x-10;//移動量
}

| | コメント (0)

[BCB] タスクバーに表示されないアプリを作る

プロジェクトのソースファイルを以下のように書き換えます。ソースファイルは「プロジェクト」-「ソース表示」で表示できます。

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  try
  {
    Application->Initialize();
    //タスクバーからアイコンを消す
    ShowWindow(Application->Handle, SW_HIDE);
    SetWindowLong(Application->Handle, GWL_EXSTYLE,
      GetWindowLong(Application->Handle, GWL_EXSTYLE) | WS_EX_TOOLWINDOW);
    Application->CreateForm(__classid(TForm1), &Form1);
    Application->Run();
  }
  catch (Exception &exception)
  {
    Application->ShowException(&exception);
  }
       :

| | コメント (0)

[BCB] StringGridを列を指定してソートする(バブルソート)

以下はStringGridで列を指定してソートする手続きです。1つ目の引数にはソートするStringGridを、2つ目の引数には何列目でソートするかを指定します。なお、以下の例ではデータを文字列としてソートしていますが、データを比較するif文を書き換えれば数値としてソートすることも可能です。その場合は、比較する2つデータをStrToIntなどで整数に直してから比較することになります。

void __fastcall TForm1::StringGridSort(TStringGrid *Grid, int SortCol)
{
 for (int i=Grid->FixedRows;iRowCount-1;i++) {
  for (int j=Grid->RowCount-1;j>i;j--) {
   if (Grid->Cells[SortCol][j-1]>Grid->Cells[SortCol][j]) {//データを比較
    //2つの行を入れ替える
    AnsiString TmpStr=Grid->Rows[j-1]->CommaText;
    Grid->Rows[j-1]->CommaText=Grid->Rows[j]->CommaText;
    Grid->Rows[j]->CommaText=TmpStr;
   }
  }
 }
}

この手続きはバブルソートという方法を使っています。時間のかかるソート法ですので行数が多くなると固まったようになるかもしれません。

| | コメント (0)

[BCB] StringGridでクリックされた場所のRowとColを取得

StringGridで、一番上の行につくったFixedRowがクリックされたときに、クリックされた列をキーにしてデータをソートしたいということがあります。マウスクリックされた場所が、何行、何列のセルなのかは以下のようにして取得することができます。

void __fastcall TSentenceSimForm::StringGrid1MouseUp(TObject *Sender,
   TMouseButton Button, TShiftState Shift, int X, int Y)
{
 int ARow,ACol;
 StringGrid1->MouseToCell(X,Y,ACol,ARow);

 //AColに列、ARowに行番号が格納される
 
 if (ARow!=0) return; //クリックされたのが一番上の行じゃなかったらreturn
 else StringGridSort(ACol); //ACol列でソート
}

上の例のStringGridSortは自分で定義する必要があります。

| | コメント (0)

[BCB] フォルダを削除する

RemoveDirectoryを使います。

| | コメント (0)

[BCB] バイナリデータをBase64エンコードする

入力されたバイナリデータをBase64エンコードする関数です。引数Bufには入力データ列を、Lengthにはその長さを指定します。エンコードの結果はAnsiString型の文字列で返されます。

AnsiString __fastcall Encode64(Byte *Buf,int Length)
{
 char *Codes64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 int Byte3=0;
 AnsiString Result="";

 for (int i=0;i<Length;i++) {
  Byte3=(Byte3<<8)+(int)Buf[i];
  if ((i+1)%3==0) {
   Result=Result+Codes64[(Byte3>>18)&0x3F];
   Result=Result+Codes64[(Byte3>>12)&0x3F];
   Result=Result+Codes64[(Byte3>>6 )&0x3F];
   Result=Result+Codes64[(Byte3  )&0x3F];

   Byte3=0;
  }
 }

 int Rest=Length%3;
 switch (Rest) {
 case 1:
  Byte3=Byte3<<4;
  Result=Result+Codes64[(Byte3>>6 )&0x3F];
  Result=Result+Codes64[(Byte3  )&0x3F];
  Result=Result+"==";
  break;
 case 2:
  Byte3=Byte3<<2;
  Result=Result+Codes64[(Byte3>>12)&0x3F];
  Result=Result+Codes64[(Byte3>>6 )&0x3F];
  Result=Result+Codes64[(Byte3  )&0x3F];
  Result=Result+"=";
  break;
 }
 return Result;
}

| | コメント (0)

[BCB] フォームが最大化(最小化)されているか調べる

フォームの状態を調べるにはWindowStateプロパティを使用します。

{
 switch (Form1->WindowState) {
 case wsMaximized:
  //最大化されている
  break;
 case wsMinimized:
  //最小化されている
  break;
 case wsNormal:
  //どちらでもない
  break;
 }
}

| | コメント (0)

[BCB] OSの名前を取得する(簡易版)

ヘッダ

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Windows.hpp>

class TSysOSVersionInfo
{
private:
 AnsiString FProductID;
 AnsiString FProductName;
 DWORD FServicePackVersion;
 DWORD FVersionMajor;
 DWORD FVersionMinor;
 DWORD FVersionBuild;
 AnsiString FCSDVersion;

 bool FIsWinNT;
public:
 __fastcall TSysOSVersionInfo(void);
 __fastcall ~TSysOSVersionInfo(void);

 __property AnsiString ProductID={read=FProductID};
 __property AnsiString ProductName={read=FProductName};
 __property AnsiString ProductType={read=FProductType};
 __property DWORD ServicePackVersion={read=FServicePackVersion};
 __property DWORD VersionMajor={read=FVersionMajor};
 __property DWORD VersionMinor={read=FVersionMinor};
 __property DWORD VersionBuild={read=FVersionBuild};
 __property AnsiString CSDVersion={read=FCSDVersion};
};


#endif

ソース

//---------------------------------------------------------------------------


#pragma hdrstop

#include "Unit1.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#include <windows.h>
#include <Registry.hpp>

//---------------------------------------------------------------------------
__fastcall TSysOSVersionInfo::TSysOSVersionInfo(void)
{
 TSystemInfo SystemInfo;

 memset(&SystemInfo, 0x00, sizeof(SystemInfo));
 GetSystemInfo(&SystemInfo);

 FIsWinNT = (Win32Platform == VER_PLATFORM_WIN32_NT);

 //ProductID,ProductName
 TRegistry *Reg=new TRegistry(KEY_READ);
 try {
  bool Res;
  Reg->RootKey=HKEY_LOCAL_MACHINE;
  if (FIsWinNT) Res=Reg->OpenKeyReadOnly("Software\\Microsoft\\Windows NT\\CurrentVersion");
  else Res=Reg->OpenKeyReadOnly("Software\\Microsoft\\Windows\\CurrentVersion");

  if (Res) {
   FProductID=Reg->ReadString("ProductID");
   FProductName=Reg->ReadString("ProductName");
  }

  Reg->CloseKey();
 } __finally {
  delete Reg;
 }
 FVersionMajor=Win32MajorVersion;
 FVersionMinor=Win32MinorVersion;
 FVersionBuild=Win32BuildNumber;
 FCSDVersion=Win32CSDVersion;
}
//---------------------------------------------------------------------------
__fastcall TSysOSVersionInfo::~TSysOSVersionInfo(void)
{

}
//---------------------------------------------------------------------------

| | コメント (0)

[BCB] 世界協定時刻(UTC)をローカルタイムに変換

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TSystemTime STime,LTime;
 TIME_ZONE_INFORMATION TzInfo;

 //タイムゾーン情報を取得
 GetTimeZoneInformation( &TzInfo );
 //現在のシステム時刻(UTC)を取得
 GetSystemTime(&STime);

 //タイムゾーン情報を使ってローカルタイムに変換
 SystemTimeToTzSpecificLocalTime(&TzInfo,&STime,&LTime);

 //結果を表示
 AnsiString Str;
 Str.printf("%02d:%02d:%02d",LTime.wHour,LTime.wMinute,LTime.wSecond);
 Label1->Caption=Str;
}

| | コメント (0)

[BCB] 文字が数字かどうか調べる

bool __fastcall IsNumeric(char c)
{
 return ((c>='0') && (c<='9'));
}

| | コメント (0)

[BCB] TSystemTime(_SYSTEMTIME)とTDateTimeの変換

TSystemTimeをTDateTime型に変換

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TDateTime DateTime;
 TSystemTime SystemTime;

 GetLocalTime(&SystemTime);
 //変換
 DateTime=SystemTimeToDateTime(SystemTime);
}

TDateTimeをTSystemTimeに変換

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TDateTime DateTime;
 TSystemTime SystemTime;

 DateTime=Now();
 //変換
 DateTimeToSystemTime(DateTime,&SystemTime);
}

| | コメント (0)

[BCB] 世界協定時刻(UTC)を取得する

GetSystemTimeを使用します。引数にはTSystemTime構造体へのポインタを指定します。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TSystemTime Stime;
 GetSystemTime(&Stime);

 AnsiString Str;
 Str.printf("%d/%d/%d",Stime.wYear,Stime.wMonth,Stime.wDay);
 Lable1->Caption=Str;
}

TSystemTime構造体には次の値が格納されます。

wYear
wMonth
wDayOfWeek曜日(日:0、月:1、..、土:6)
wDay
wHour
wMinute
wSecond
wMillisecondsミリ秒

なお、ローカル時間はGetLocalTimeで取得することができます。

| | コメント (0)

[BCB] TColorをRGB値に変換する

TColorをR,G,Bの値に分解する関数です。

void TColor2RGB(TColor Color, Byte &R, Byte &G, Byte &B)
{
 int RGB=ColorToRGB(Color);

 R=RGB&0xFF;
 G=(RGB>>8)&0xFF;
 B=(RGB>>16)&0xFF;
}

| | コメント (0)

[BCB] システムの音を鳴らす

MessageBeepを使うと、コントロールパネルの[サウンド]で設定された音を鳴らすことができます。引数には音の種類を指定します。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 MessageBeep(MB_ICONASTERISK);
}

指定できる音の種類

0xFFFFFFFF標準のビープ音
MB_ICONASTERISKシステム 情報
MB_ICONEXCLAMATIONシステム 警告
MB_ICONHANDシステム エラー
MB_ICONQUESTIONシステム 問い合わせ
MB_OKデフォルトの警告音

| | コメント (0)

[BCB] システムのアイコンを取得する

LoadIconを使用すると、システムで使用されるアイコン(MessageDialogなどに表示されるエラーや警告のアイコンなど)を取得できます。

void __fastcall TForm1::FormCreate(TObject *Sender)
{
 //Image1にエラーのアイコンを表示
 Image1->Picture->Icon->Handle = LoadIcon(0, IDI_HAND);
}

他にも以下のような値を指定できます。

IDI_APPLICATION
IDI_HAND
IDI_QUESTION
IDI_EXCLAMATION
IDI_ASTERISK
IDI_WINLOGO

| | コメント (0)

[BCB] ファイル名の拡張子を変更する

ファイル名の拡張子を変更するにはChangeFileExt関数を使います。

#include <SysUtils.hpp>

//拡張子を取得
Filename="C:\\tmp\\test.ini";
Result=ChangeFileExt(Filename,".htm");

引数には元のファイル名と拡張子を「.」を含めた形で指定します。上の例の場合、Resultは「C:\tmp\test.htm」となります。

ChangeFileExt(Filename,"");
のようにすると拡張子を取り除くこともできます。

|

[BCB] ファイルの拡張子を取得する

ファイルの拡張子を取得するにはExtractFileExt関数を使います。

#include <SysUtils.hpp>

//拡張子を取得
Filename="C:\\tmp\\test.ini";
FileExt=ExtractFileExt(Filename);

関数を実行すると変数FileExtには、拡張子が「.」を含めた形で格納されます。上の例の場合はFileExtの内容は「.ini」となります。

拡張子がない場合は空の文字列が返されます。

|

[BCB] ダイアログを動的に作成する

ダイアログを動的に作成する方法です。以下はTSaveDialogの例です。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TSaveDialog *Dlg;

 Dlg=new TSaveDialog(this);
 //フィルタを設定
 Dlg->Filter="テキストファイル(*.txt)|*.txt|HTMLファイル(*.htm)|*.htm|すべてのファイル|*.*";
 //オプションを設定
 Dlg->Options=Dlg->Options<<ofOverwritePrompt<<ofPathMustExist;
 Dlg->FileName="list.txt";

 if (Dlg->Execute()) {
  //処理をする
 }
 
 delete Dlg;
}

|

[BCB] Delphiのwith文に対応するものは?

Delphiにはwith文を使って、長いコードを省略することができます。例えば以下のようです。

with Form1.Image1.Picture.Bitmap.Canvas do begin
 MoveTo(0,0);
 LineTo(1,1);
end;

BCBでも使いたいところですが残念ながらBCBにはwith文はありません。その代わりに次のようにして書くことができます。

TCanvas *Canvas=Form1->Image1->Picture->Bitmap->Canvas;
Canvas->MoveTo(0,0);
Canvas->LineTo(1,1);

| | コメント (0)

[BCB] 3桁ごとに数字をカンマで区切る

FormatFloat('#,##0', Value);

これだけでOK。

|

[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);

| | コメント (0)

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

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

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

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

| | コメント (0)

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

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

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

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

| | コメント (0)

[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)) {
  //作成に成功
 }
}

| | コメント (0)

[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すべてのファイル

| | コメント (0)

[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);

| | コメント (0)

[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();
}
//---------------------------------------------------------------------------

| | コメント (0)

[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;
}
//-----------------------------------------------------------------

| | コメント (0)

[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日(グレゴリオ暦施行日)以前については有効ではありませんのでご注意ください。

| | コメント (0)

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

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

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

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

| | コメント (0)

[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));
}

| | コメント (0)

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

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

$(BCB)/Help/index.html

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

| | コメント (0)

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

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

| | コメント (0)

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

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

Action = caFree;

| | コメント (0)

[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

| | コメント (0)

[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;

| | コメント (0)

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

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

| | コメント (0)

[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;

| | コメント (0)

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

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

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

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

| | コメント (0)

[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() が指す領域を変更するような処理をしてはいけません。

| | コメント (0)

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

char *buf=NULL;

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

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

| | コメント (0)

[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型の最大値

| | コメント (0)

[BCB] MAX、MINマクロ

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

| | コメント (0)

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

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

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

| | コメント (0)

[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;
}

| | コメント (0)

[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;
 }
}

| | コメント (0)

[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
 */
}

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

| | コメント (0)