初版作成 2004.07.21
最終更新 2024.04.01
プロジェクトを新規作成して、「プロジェクトに名前を付けて保存」 した後、コンパイルすると [リンカ 致命的エラー] Fatal: ファイル名が必要 : というエラーが出ることがある。ディレクトリの深さが深すぎると、 エラーが出るように思われる。以下のように対処する。 **.dpr ファイルをエディタで開くと、 <INCLUDEPATH value=""C:\Program Files\Borland\CBuilder6\Projects";[この部分];$(BCB)\include;$(BCB)\include\vcl"/> <LIBPATH value=""C:\Program Files\Borland\CBuilder6\Projects";[この部分];$(BCB)\lib\obj;$(BCB)\lib"/> の [この部分] にプロジェクトを保存したフォルダが絶対パスで入っている。 LIBPATH に含まれている [この部分] を削除するとエラーは出なくなる。謎である。 ネットワークドライブを使用したときも同様のエラーがでる。この時にも 上記の対処法が有効か否かは未確認である。
1.「ファイル」→「新規作成」→「アプリケーション」で新規アプリケーションを作成し、 「ファイル」→「プロジェクトに名前を付けて保存」でフォルダに保存する。 2.「プロジェクト」→「プロジェクトから削除」で、全てのフォーム、リソースを削除する。 3. 移行元のプロジェクトのフォルダから、cpp, h, dfm, res ファイルをコピーしてくる。 新規アプリケーション作成時に自動生成された Unit1.* などは不要なので削除する。 4. 「プロジェクト」→「プロジェクトに追加」で cpp, res ファイルを追加する。
バージョン 1.0 のプロジェクトファイルを 5.0 用に移行する方法 1.「ファイル」→「プロジェクトを開く」→「ファイルの種類」を 「C++Builder 1.0 のプロジェクト(mak)」でプロジェクトファイル ◯◯.mak を開く。 2. ソースファイルのうち、#include <stdio.h> を記述していない ファイルは記述する。 3. 「ファイル」→「全て保存」で ◯◯.dpr ファイルを作成する。 4. ◯◯.dpr をエディタで開き、LIBRARIES と SPARELIBS の項目の部分を 以下のように直す。 <LIBRARIES value="vcl50.lib"> <SPARELIBS value="vcl50.lib"> 5.「ファイル」→「全て閉じる」のあと、「ファイル」→「プロジェクトを開く」 で修正した ◯◯.dpr ファイルを開き直す。 6. 「プロジェクト」→「◯◯を再構築」でコンパイル〜リンクをやり直す。
C++Builder 1.0 ではデフォルトでランタイムライブラリ不要の exe ファイル を作成していたが、C++Builder 5.0 ではデフォルトでランタイムライブラリが 必要な exe ファイルを作成する。C++Builder 5.0 でランタイムライブラリ 不要の exe ファイルを作成する方法は以下の通り。 「プロジェクト」→「オプション」のウィンドウにおいて > 「パッケージ」で「実行時パッケージを使って構築」のチェックを外す > 「リンカ」で「共有 RTL DLL を使う」のチェックを外す
SelectDirectory という関数を使えばよい。 使い方はヘルプの「例」を参照。SelectDirectory を使うには #include <FileCtrl.hpp> が必要であるが、このインクルード文は *.cpp に書いてはいけない。 *.h の中に書く必要がある。 *.cpp の中に書き、かつ「実行時パッケージを使って構築」の チェックを外した場合、「外部参照が未解決です」というリンクエラーが発生する。
Form1.Scaled = false : 起動するディスプレイの解像度によらず
固定サイズのウィンドウを開く
Form1.Posision = poDefaultPosOnly : サイズは設計時のままで、
位置は Windows が規定する位置にウィンドウを開く
Form1.BorderIcons.biMaximize = false : 最大化できなくする
情報源 http://tokyo.cool.ne.jp/purasupurasu/bcb.html#n9 フォーム生成時に、ボタンの属性を Windows の API を使って変更する。 Button1->Caption = "ab............\n............"; long bsp; // Window の情報を取得する API。ボタンもウィンドウの一種 GWL_STYLE はスタイルを取得する bsp = GetWindowLong(Button1->Handle, GWL_STYLE); // Window の属性を定義する。ウィンドウハンドル, 属性, 新しい値 SetWindowLong(Button1->Handle, GWL_STYLE, bsp | BS_MULTILINE);
RadioGroup1->Items->Strings[0] = "abc";
RadioGroup1->Items->Add("abc");
RadioGroup1->Items->Delete("abc");
index = RadioGroup1->Items->Indexof("abc");
RadioGroup1->Items->Count;
「ファイル」→「新規作成」→「その他」→「スレッドオブジェクト」
でスレッド用のユニットが作成される。
スレッド用ユニットが Unit2.cpp でメインフォームのコードが Unit1.cpp だと
すると、お互いに #include "Unit1.h" のようにインクルードしあうことが
必要である。
TThread を継承して新しいスレッドクラスが作成される。
名前を TMyThread とすると
__fastcall TMyThread::TMyThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
となり、コンストラクタの引数である bool 型変数を TThread の
コンストラクタに渡す。
false にすると new の瞬間に開始する。
true にすると Resume() メソッドで明示的に開始する。
false にするとコンストラクタが終了する前に Execute が開始するので、
true を推奨するとヘルプに書いてある。
私は以下のようにしている。
コンストラクタの引数を変更したときは、Unit2.h も書き換えることを
忘れないように。
__fastcall TMyThread::TMyThread( 初期化用の引数 )
: TThread(true)
{
初期化処理
}
コンストラクタは以下のようになる。
TMyThread *thread;
thread = new TMyThread( 初期化用の引数 );
thread->Resume();
スレッド本体を関数 Execute() の中に記述する。
しかし、Execute() は呼ぶことが出来ない。Resume() で開始させる。
Terminate() メソッドを呼ぶと、デフォルトで用意されている
変数 Terminated が true となる。
Execute の中で無限ループを組む場合は、以下の処理を入れる。
if ( Terminated == true ) return;
Execute() から return すると、スレッドのインスタンスは消滅するようだ。
もう一度、Resume() しても Execute() は実行されない。
一時停止させるには Suspend() メソッドを呼ぶ。
以下のことは大変重要である。
ボタンを押して呼ばれるコールバック関数の中で、
スレッドを new して Resume() したとき、そのコールバック関数
から return するまで、スレッドは開始しない。例えば、
以下のような場合、thread->Execute() が
開始するのは Sleep(1000) の後である。
void __fastcall TForm1::Button1Click(TObject *Sender)
{
thread = new TestThread(Memo1);
thread->Resume();
Sleep(1000);
}
スレッドからメインフォームのメソッドを呼ぶとき、
Symchronize メソッドを使わないと、効かないことがある。
以下のように記述する。
-------- Unit2.h ----------
protected:
void __fastcall Execute();
void __fastcall Form_Hide();
-------- Unit2.cpp ---------
void __fastcall TMyThread::Form_Hide()
{
Form1->Hide();
}
void __fastcall TMyThread::Execute()
{
// TODO : スレッドとして実行したいコードを以下に記述 */
Synchronize(Form_Hide);
----------- ここまで -----------
Unit1.cpp とUnit2.cpp で共通の変数を使うとき、 Unit1.h の中で int abc; と 宣言して Unit1.cpp と Unit2.cpp において #include "Unit1.h" とするのは ダメである。別々の変数と見なされる。