C-BuilderでEditのデーターが変化した時に二重割り込みを防ぐ方法を教えてください

このQ&Aのポイント
  • C-BuilderでEditのデーターが変化した時に二重割り込みが発生する問題があります。現在、bInhibitフラグを使用して二重割り込みを防いでいますが、タイミングによってはまだ問題が発生しています。他の方法を教えていただきたいです。
  • Editの内容が変化した時にエラーメッセージを表示させ、内容を以前の状態に戻している処理がありますが、その状態でも再度OnChangeイベントが発生してしまいます。bInhibitフラグを使用して再度OnChangeイベントの発生を防いでいますが、まだ問題が解消されていません。
  • Editの内容が変化した時に二重割り込みが発生してしまう問題があります。bInhibitフラグを使用して現在は二重割り込みを防いでいますが、まだ完全に問題が解決されていません。他の解決方法があれば教えていただきたいです。
回答を見る
  • ベストアンサー

C-Builder OnChangeをマスク

C-BuilderでEditのデーターが変化した時、ある処理をしています。 その処理の中で、入力内容が正しく無い時はエラーメッセージを表示させ、Editの内容を入力された以前の状態に戻して居る為、その状態でも再度OnChangeイベントが発生してしまいます。 現在はbInhibitフラグを作って、これをルーチン内でtrueにする事で、再度OnChangeイベントが発生した時にルーチンの最初でreturnさせて二重割り込みを防ごうとしていますが、タイミングによっては二重割り込みが発生してしまいます。 これが内部での変更で無ければ Edit1->Enabled = false; とする事により、二重の割り込みは防げますが、今回はEdit1Changeの中で書き換えを行っている為、これでは二重割り込みを防げません。 何か二重割り込みを防ぐ方法がありましたらお教え下さい。 宜しくお願い致します。 bool bInhibit = false; void __fastcall TForm1::Edit1Change(TObject *Sender) { if( bInhibit == true ) return;   bInhibit = true;   -------- bInhibit = false; } }

質問者が選んだベストアンサー

  • ベストアンサー
  • au2010
  • ベストアンサー率83% (5/6)
回答No.1

あまり変わらないかも知れませんが、OnChangeイベントの頭でイベントにNULLを設定してみたらどうでしょう? void __fastcall TForm1::Edit1Change(TObject *Sender) { dynamic_cast<TEdit*>(Sender)->OnChange = NULL;   -------- dynamic_cast<TEdit*>(Sender)->OnChange = Edit1Change; }

TinyPine
質問者

お礼

ご回答ありがとうございます。 OnChangeが制御出来るのですね。 このやり方は知りませんでした。 明日、会社で試して見たいと思います。 ありがとう御座いました。

TinyPine
質問者

補足

本日、会社で試して見ました。 この方法では二重割り込みは発生しませんでした。 その他のマスクにも使えますね。 ありがとう御座いました。

その他の回答 (1)

回答No.2

下記、いずれも未検証ですが…… 【案1】 void __fastcall TForm1::Edit1Change(TObject *Sender) { Edit1->Enabled = false; // とりあえず、これ以降割り込み発生しないようにして Application->ProcessMessages(); //イベントループを一回りさせる(これで、内部状態も反映される) // 実際の処理 Edit1->Enabled = true; // 元に戻す。 } 【案2】 実際の処理を、OnChange ハンドラの外でやる。 bool isChagned = false; void __fastcall TForm1::Edit1Change(TObject *Sender) { Edit1->Enabled = false; // とりあえず、これ以降割り込み発生しないようにして isChanged = true; // 変化したというフラグを立てて Timer1->Enabled = true; // 定期的な監視をスタートして、処理終了 } だけにして、定期的に、isChanged をチェックするという方法です。 定期的なチェックは、Timer を使って、タイムラグが気にならない程度の頻度でハンドラを起動し、 void __fastcall TForm1::Timer1Timer(TObject *Sender) { // 実際の処理 // 処理が終わったら、 Timer1->Enabled = false; // 定期的な監視を終了 isChanged = false; // 変化しフラグをクリアして、 Edit1->Enabled = true; // 割り込みが発生できるようにして、処理終了 } こんな感じで。 OnChage() を抜けて、割り込みが発生しない状態になってから、編集が始まるというのがみそです。 マルチスレッドで構成できれば、もう少しきれいにできると思います。

TinyPine
質問者

お礼

ご回答ありがとう御座います。 Application->ProcessMessages();の方は既に検討済みです。 やはり外部で制御する必要があるのでしょうか。 メインテナンスの事を考えると出来るだけ内部でやりたいと思っております。 今は2重にフラグを作って対応して居ますが、このEdit自体実際はダイナミックキャストを使って居ますので、そこら辺のタイムラグ等で最初のフラグが認識されない事があるのかも知れません。 2重にしてどうにか正常動作?して居ますので、特に割り込み禁止プロパティー等が無ければ今のプログラムで行こうと思っております。 ありがとう御座いました。

関連するQ&A

  • VB.net 割り込みの禁止

    Borland C-Builder++の内容をVB.net 2010に書き換えて居る者です。 TextBox等の割り込みを一時的に禁止したいのですが、良い方法はありませんでしょうか。 無ければフラグを用いて、フラグが立っている時のみ処理をバイパスさせる事を考えて居ます。 Builder では ComboBox1->OnChange = NULL ; とコーディングする事により、 void __fastcall TForm1::ComboBox1Change(TObject *Sender) { Edit1->Text = ComboBox1->Text; } への割り込みを禁止出来、 ComboBox->OnChange = ComboBox1Change; とコーディングする事により割り込みを再開出来ました。 これを void __fastcall TForm1::ComboBoxChange(TObject *Sender) {     ComboBox1->OnChange = NULL ; Edit1->Text = ComboBox1->Text;     ComboBox->OnChange = ComboBox1Change; } とコーディングする事により、2重割り込みを防止していました。 VBでこの様にイベント割り込みを一時的に禁止にする方法はありますでしょうか。 宜しくご回答下さい。

  • AVIファイルを読み込む方法

    C++でプログラミング中の者です。 使っているコンポーネントはanimate、MediaPlayer、Edit、Botton、OpenDialogです。 OpenDialogで選択したファイル名をEditに表示させ、Mediaplayerを使ってAnimateに表示させるプログラミングをしたいと思っています。 なかなかうまくいかないので、アドバイスお願いいたします。 次のは現在のプログラムです。 #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { //OpenDialog1->DefaultExt = "AVI"; //OpenDialog1->FileName = "*.avi"; if(OpenDialog1->Execute()==true){ // ファイル名が選択されたときに実行する処理  Edit1->Text=OpenDialog1->FileName; //Edit1に選択したファイル名を表示 //Animate1->Active=LoadFromFile(OpenDialog1->FileName); } } //--------------------------------------------------------------------------- void __fastcall TForm1::Edit1Change(TObject *Sender) { MediaPlayer1->Open(); MediaPlayer1->Play(); } //---------------------------------- よろしくお願いします。

  • C-Builderで数値(数字)以外を入力出来ない様にしたい。

    C-Builder V5 で数値(数字)を入力すべきところで、実行時に文字等を入力すると、システムからエラーメッセージが表示されるので、これを防ぐ為にEditで入力時に数字以外をはじきたいのですが、可能でしょうか。 以前C-Builder V4で作った時は出来た様な気がしたのですが、どの様にやったか思い出せないでいます。 ネットではC-Builderのサンプルが見つからず、Delphiのサンプルでは昔の記憶と同じ処理を行っていましたが、これだと文字判定以前にEditの枠に既に文字が入ってしまっており、文字の排除が出来ませんでした。 どなたか数字以外をはじく方法ご存知の方、お教え下さい。 // Edit1->ImeMode = imDisable; // 初期化部分で実行 void __fastcall TForm1::Edit1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { if(Key<48 || Key>57) { Key = 0; } }

  • BorlandC++Builder5.0でリンカエラー

    現在A/D変換ボードの制御をしようとしています。 ボードのインストールも行なったのですが、以下のエラーが出て困っています。 外部シンボル 'AdOpen' が未解決(C:\PROGRAM FILES\BORLAND\CBUILDER5\PROJECTS\MAG\MAIN.OBJ が参照)と出てしまいます。 mainはシンプルなのですが... void __fastcall TForm1::OpenDevClick(TObject*Sender) { device_handle = AdOpen("FBIAD1"); if(device_handle == INVALID_HANDLE_VALUE){ ShowMessage("Err : デバイスのオープンに失敗"); return; } } そもそもこのエラーはなぜ出るのですか?

  • Borland社のコンパイラを使ったDLL

    C++BuilderでDLLファイルを使っておりますが、Vectorコンテナの値をコールバック出来ませんでした。Vectorコンテナを使ったコールバックを可能とする記述方法を教えてください。 Edit1には、思惑通りに102が返ります。Edit2には、1が、Edit3には2が返ります。この例では、201、202を返したいのです。 本体側 #include <vector> ・ ・ extern "C" __declspec(dllimport) int __stdcall test(int*,vector<int>); #pragma package(smart_init) #pragma resource "*.dfm" using namespace std; TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { vector<int> b; b.push_back(1); b.push_back(2); int *a; *a=1; Edit1->Text = IntToStr(test(a,b)); Edit2->Text = IntToStr(b[0]); Edit3->Text = IntToStr(b[1]); b.clear(); dll側 extern "C" __declspec(dllexport) int __stdcall test(int*,vector<int>*);//コンテナの引数の実験 ・ ・ //----------------------------------------------------------------------------- int __stdcall test(int *a,vector<int> &b) { //dllの引数の可能性の実験 for(unsigned int i;i<b.size();i++){ b[i] +=200; } *a+=1; return *a+100; } //-----------------------------------------------------------------------------

  • onchangeイベントを強制的に発生させる

    お世話になります。 onchangeイベントをjavascriptで強制的に動作させたいと思っております。 発生させたい場合 ・ユーザーがtextボックスを入力 ・リンクボタンを押下した場合 簡単なことなのかもしれませんが、 ご教授よろしくお願いいたします。 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <script type="text/javascript"> function change(){ alert('test'); } function update(){ document.getElementById('1').value = "update"; document.getElementById('1').onchange = change; } </script> <input id="1" type="text" value="1" onchange="change();"> <a href="javascript:update();">update</a>

  • IE7のonChangeイベントを使用して入力チェック

    textフィールドのonchangeイベントでjavascriptの入力チェックを行い、エラー時はフォーカスをエラー項目に戻し、カーソルを移動できないようにしたいです。 --想定している動作 (1)test1_fieldに1以外の値を入力し、tabなどで移動する。 (2)javascriptのcheck1()でエラーチェック。エラー「test1_field NG」が表示され、カーソルがtest1_fieldに戻る。 再度、カーソルを移動しようとすると、(2)の動作を行う。 --実際の動作 IE6(XP+IE6sp2)では、以下のテストスクリプトで想定している動作をしていたのですが、IE7(Vista+IE7)では、return falseを返しても、test2_fieldにフォーカスが移動できてしまいます。 --テストコード <html> <script> function check1(obj){ if (obj.value==1){ return true; } alert("test1_field NG"); obj.focus(); obj.select(); return false; } function check2(obj){ if (obj.value==2){ return true; } alert("test2_field NG"); obj.focus(); obj.select(); return false; } </script> test1_field:<input type="text" name="test1_field" onchange="return check1(this)" >(1のみOK)<br><br> test2_field:<input type="text" name="test2_field" onchange="return check2(this)" >(2のみOK) </html> 記述等に間違いがあるのでしょうか? ご教授いたがければ幸いです。

  • 動的に作ったリッチエディットのイベント

    toshi_ynと申します。 動的に作ったRichEditのサイズを調整できるようにOnResizeRequestイベントを 設定したつもりなのですが、コンパイルでエラーがでます。 いろいろなTipsを見ながら作ったので、どこが間違っているのか 分からず困っております。 こちらの環境はWIn98, Borland C++Builder Ver.4です。 どなたか、助けをお願いします。 [C++ エラー] Calender1.cpp(1092): E2034 Cannot convert 'void (_fastcall * (_closure )(TObject *,TRect &))(TObject *,TRect &)' to 'void (_fastcall * (_closure )(TObject *,const TRect &))(TObject *,const TRect &)'. //--コード-- Unit.h private: // ユーザー宣言 void __fastcall TForm1::Redit_ResizeRequest(TObject *Sender,TRect &Rect); Unit.cpp //----------- Redit[Num] =new TRichEdit(Owner); Redit[Num]->Parent = pnl[Num]; Redit[Num]->BorderStyle=bsNone; Redit[Num]->ScrollBars=ssNone; Redit[Num]->ReadOnly=true; Redit[Num]->Tag=Num; Tag=Num; Redit[Num]->Width=10; Redit[Num]->Height=10; Redit[Num]->PlainText=false; Redit[Num]->Cursor=crArrow; Redit[Num]->OnMouseDown=Redit_MouseDown; Redit[Num]->OnDragOver=Redit_DragOver; Redit[Num]->OnResizeRequest=Redit_ResizeRequest; ←ここでエラー //------------- void __fastcall TForm1::Redit_ResizeRequest(TObject *Sender,TRect &Rect) { Redit[Tag]->BoundsRect = Rect; } //------------

  • グループボックスのBN_CLICKEDイベント

    グループボックスコントロールのBN_CLICKEDイベントが発生しません。 NotifyプロパティはTrueとしています。 その他のプロパティもTrue、Falseどちらも試してみましたが 割り込みに入りません。 何か足りない部分があるのでしょうか? *VB6.0からVC++2010への移植作業中です。  VB6.0の Frame Control をVC++の Groupe Box Control としました。

  • ExcelマクロのApplication.EnableEvents

    Sub AAA()   Application.EnableEvents = False   If a = 0 then     処理A   End If   Application.EnableEvents = True End Sub このようなコードを組んでいます。 処理Aは、他シートへの書込みを行っており、 他シートのWorksheet_Changeイベントが動いて欲しくないので、 上記の位置にApplication.EnableEventsのFalseとTrueを入れたのですが、 (FalseとTrueを入れた位置は「If文の前後」ではなく、「コードの最初と最後」です) 処理Aによって他シートのWorksheet_Changeイベントも動きました。 ここで、  Application.EnableEvents = False  処理A  Application.EnableEvents = True のように記述したら、処理Aによる他シートのWorksheet_Changeイベントは止められました。 動かしたくない処理がある場合は、 その処理を行っている部分をピンポイントでFalseとTrueで挟まないといけないのでしょうか。 (最初と最後に宣言するのではダメなのでしょうか) それとも今回のような動作をした要因は別にあるのでしょうか。

専門家に質問してみよう