2009では問題のなかったプログラムですが、XE2でコンパイルするとこのエラーが出ます。
このTimerで呼び出したウィンドウの中でも、Timerを使って作業をさせていますが、このときエラーになるようです。
手動(ボタン)で同じウィンドウを操作する時はエラーになりませんので。
この問題を避けるために、呼び出したウィンドウの中でOnActivateで作業させると仕事はするのですが、ウィンドウがいくつも立ち上がるという問題が生じました。
私の知識では、お手上げです。
どうかよろしくお願いします。
OnActivateで試したという事で、起動時に1回だけ該当のウィンドウを表示したいという前提で。
呼び出し元のフォームのprivateあたりにフラグを宣言して
OnActivateでこのウィンドウを呼び出したらフラグを立てて
2度目には表示しないってのが一番簡単かな。
フラグを論理型でなく数値にすれば、その値でウィンドウを開くかどうか
判断したりすることもできます。
ん、タイマーを使って呼び出すとき、Intervalの値はいくつくらいでしょうか?
その値によっては、OnTimerイベントですぐにEnabledをFalseにしないと
同じウィンドウを何度も開こうとしますが。
でも、2009では動いてたんだから、その辺は処理済でしょうけど。
Questさん、ありがとうございます。
まず,Intervalは60000にしています。まあ、これは問題ないと思います。
次に、フラグを立てる件ですが、これは変数を使って制御しているんですが、まったく役立ちません。
なんか、想像なんですが、呼び出されたformのonactivateが終わったら元のformに信号が帰って、formを作るのをやめるとか?
OnActivateで作業させると、その信号が来ないのでいくつもできるのかなとか??
参考ですが、OnCreate、OnShow、OnActivateの順で実行されるようで、OnShow内で作業させると、呼び出されたFormが立ち上がりません。
>フラグを立てる件ですが、これは変数を使って制御しているんですが、まったく役立ちません。
具体的にはどのようにしているんでしょう?
変数はどこで宣言していますか?
Type
TForm1 = class(TForm)
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
Flag: integer;
.
.
.
procedure TForm1.FormCreate(Sender: TObject);
begin
Flag := 0
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
if Flag = 0 then
begin
Flag := 1;
//別ウィンドウを表示
end
end
とすれば、一回だけ表示されるはずですが。
Questさん、こんばんは。
お世話になります。
次のようにしていましたが、いくつも(最大8個位?)立ち上がりました。
timestepは別formで定義していて、usesを使って呼び出しています。
procedure form1.timer1timer(Sender:TObject);
begin
if timestep=1 then
begin
timestep:=2;
//form2呼び出し
end;
以下呼び出しで取得したデータの処理
end;
呼び出したForm2で,onActivateを使って作業させると、作業できるんですが、いくつもform2が立ち上がります。
呼び出したForm2で、Timerを使って作業をさせようとすると
EInValidOperation のエラーが出ます。
よろしくお願いします。
Timer1.Enabled:=false;
Timestep:=1;
はIf文の前に置いています。
//form2呼び出し
のところで、具体的に何をしているのかがすご〜く気になります。
文脈から、意図的に複数のForm2のインスタンスを生成しているわけでは
なさそうですが、直接的または間接的にCreateFormしている気配がありますね...
>いくつもform2が立ち上がります。
文字どおりに捉えると、明らかに複数のForm2のインスタンスが生成されているかと。
その辺が明らかにならないと先に進めない気がします(個人的な意見です)。
断片的な情報とあやふやな表現の連続では、何もわからないと思います。
一度コードを挙げてみては。
もしかして、Form2の中でもForm2を表示しようといていませんか?
また、Form1の"if timestep=1 then "の行にブレークポイントを置いて
2度目以降にここで止まったとき、timestepがちゃんと2になっているでしょうか?
いずれにしても、他の方が仰る様に該当部分のコードや
全体としてどういった動きにしたいのかを挙げてはいかがでしょう。
1.Form1作成、表示
2.Form1のOnActiveあるいはOntimerでForm2を作成、表示(たぶんモーダル)
3.Form2で作業した結果情報を使い、Form1で続きの作業を実行
といった流れではないかと想像していますが。
簡単なプログラムを組んでみました。
form2には、edit1、button1、button2を配置しました。
これは、1個だけしか立ち上がりません。
実際に使っているFormは、richedit,memo,timer1,timer2,IdHTTPを配置しています。これは、作業をmemoにHellowを表示させるだけにしても、いくつも立ちがります。
とくに、IdHTTPはサブにもありますので、これを省いてやってみます。
また、報告します。
Timer1,timer2,IdHTTPを除いてやってみましたが、hellowを表示するだけのプログラムでも、駄目でした。いくつも立ち上がります。
また、memoとbutton1,2だけにしても、いくつも立ち上がります。
もう今日はやめます。
EInValidOperationの解消法を考えたほうがいいかなと思います。
Questさん、いつもありがとうございます。
上に書いたように、hellowを表示するだけのプログラムでもいくつも立ち上がるので、作ったりはしていません。
原因が分かりました。
ネットに接続するプログラムが問題です。
作った簡単なプログラムのform2をプログラムに組み込んで、徐々に問題になっているFormと同じにしていきました。
ネットに接続するプログラムを組み込んだら、いくつも立ちあがるようになりました。
その後、ネットに接続するプログラムを削除してHellowを表示させるようにしても、いくつも立ち上がります。
2009ではネットに接続するプログラムの多重起動ができなくなりましたが、
XE2では多重起動させるようになったのですかね。
まあ、ボタンでもできますし、いくつも立ちがるのを我慢すれば、問題はありませんし。
いくつも立ち上がりますが、そのうちの1つだけがその後のデータ処理プログラムにつながり、他のは関係ないのです。
次は、EInValidOperationもネット接続プログラムと関係しているのか調べてみます。
簡単なプログラムのForm2にネット接続プログラムを入れても、EInValidOperationのエラーは出ませんでした。
ただ、いくつも立ち上がるのは前と同じでした。
で、元のプログラムではEInValidOperationのエラーはやはり出ます。
ハッカー対策で、自動でネットに接続するのは禁じられてるんだと理解して、ボタンで対応することにしました。
解決にはしませんので、対応策をご存じの方がおられましたら、回答をお願います。
こんな漠然とした表現では誰も解決できないと思うよ。
>Timer1,timer2,IdHTTPを除いてやってみましたが、hellowを表示するだけのプログラムでも、駄目でした。いくつも立ち上がります。
>ネットに接続するプログラムを組み込んだら、いくつも立ちあがるようになりました。
そもそも どの EInValidOperation が出てるんだ?
Vcl.Forms で使用しているので
//SParentRequired = 'コントロール '#39'%s'#39' は親ウィンドウを持っていません';
//SMDIChildNotVisible = 'MDI 子フォームは非表示にできません';
//SDuplicateMenus = 'メニュー '#39'%s'#39' は別のフォームで既に使われています';
//SNoMDIForm = 'フォームを作成できません。現在アクティブな MDI フォームはありません';
//SCannotFocus = '無効/非表示ウィンドウにはフォーカスを設定できません';
//SVisibleChanged = 'OnShow や OnHide では Visible を変更できません';
こんだけあるけど
とりあえず、再現できるソースを・・・
どっちやねん?さん
>ネットに接続するプログラムを組み込んだら、いくつも立ちあがるようになりました。
→これは、1つしか立ち上がらないFormに、組み込んだらいくつも立ち上がるようになったという意味です。
>Timer1,timer2,IdHTTPを除いてやってみましたが、hellowを表示するだけのプログラムでも、駄目でした。いくつも立ち上がります。
→これは、いくつも立ち上がるとうになったFormから削除しても、立ち上がります。という意味です。
KHE00221 さん、ありがとうございます。
私も、EInVakidOPerationをどうしたらなくせるかで、質問したんですが、やっとそれを理解していただいてありがとうございます。
//SCannotFocus = '無効/非表示ウィンドウにはフォーカスを設定できません';
これが、出ます。
とにかく、2009ではまともに動いていたのです。
XE2でコンパイルしたら、エラーが出ますので、困ってます。
いくつも立ち上がるようになると、このエラーはでません。
このエラーが出るときには、立ち上がりません。
ソースについては、本物は複雑すぎてここには表示できないと思います。
で、作った簡単なプログラムを次の投稿で載せますが、ネット関連のプログラムは組み込めないので、エラーは起きません。
IdHTTPを使って、ネット接続のプログラムを組んでみてください。
Ontimerを使わないようにしたので、今は何の問題もありません。
OnTimerを使っていた時より、使い勝手が良くなったような気がします。
XE2に関しては、恐らくですが、もう質問することもないと思います。
皆さん、ありがとうございました。
Form1(IndexMain)です。
procedure TIndexMain.Button1Click(Sender: TObject);
begin
Making:=TPMaking.Create(Application);
Making.ShowModal;
Making.update;
end;
procedure TIndexMain.Button2Click(Sender: TObject);
begin
close;
end;
procedure TIndexMain.onActivate(Sender: TObject);
begin
Edit1.text:='';
timer1.interval:=1000;
TimeStep:=0;
TradeOn:=0;
Timer1.Enabled := false;
end;
procedure TIndexMain.OnKeyPress(Sender: TObject; var Key: Char);
var
s:string;
begin
if key=char(13) then
begin
s:=Edit1.text;
if S='TO' then
begin
Timep:=0;
TradeOn:=1;
TimeStep:=0;
Edit1.text:='自動';
Timer1.Enabled:=true;
end;
if S='TOF' then
begin
TradeOn:=0;
TimeStep:=0;
Edit1.text:='';
end;
end
end;
procedure TIndexMain.ontimer(Sender: TObject);
var
Str1:Pchar;
p:integer;
begin
timer1.interval:=20000;
p:=timesu;
if p<timeP+1 then exit;
TimeStep:=0;
if (TradeOn=1) and (TimeStep=0) then
begin
Timer1.Enabled := False;
TimeStep:=1;
if (TimeStep=1) then
begin
TimeStep:=2;
Making:=TPMaking.Create(Application);
Making.ShowModal;
Making.update;
end;
Timer1.Enabled := True;
end;
timep:=timesu;
end;
function TIndexMain.Timesu:integer;
Var
s:string;
p:integer;
begin
s:=TimeToStr(time); p:=InStr(1,s,':');
Timesu:=StrToInt(copy(s,1,p-1)+copy(s,P+1,2));
end;
function TIndexMain.InStr(StartPos:integer;const Str, SubStr:string):integer ;
var
pStr,p:PChar;
begin
pStr := PChar(Str);
p := AnsiStrPos(PChar(pStr+StartPos-1),PChar(SubStr));
if p = nil then
result := 0
else
result := p-pStr+1;
end;
Form2(Dmaking)です。
procedure TPMaking.OnActivate(Sender: TObject);
var
n:integer;
begin
Dmaking;
PostMessage(Handle,WM_CLOSE,0,0);
end;
procedure TPMaking.Dmaking;
var
n:integer;
begin
for n :=1 to 10 do
begin
edit1.Text:='Hellow'; application.processMessages;
sleep(1000);
edit1.Text:=''; application.processMessages;
sleep(1000);
end;
end;
procedure TPMaking.Button2Click(Sender: TObject);
begin
close;
end;
何か、あまり長いものは載せたらいけないのではと思いますが、
ネット関連のエラーが防げるようになれば、許されるかなと思いまして。
ごめんです。
書き忘れですが、上のはいくつも立ち上がるのを再現するプログラムでした。
EInValidOperation を再現するには、Form2でDmakingをネット接続プログラムに変えて、さらにDmakingを呼び出すのに、Form2でもOntimerを使って呼び出します。
いくつも立ちあがるようになったForm2を使って、OnTimerで呼び出したら、エラーは起きませんでした。
1つしか立ち上がらないForm2を使ってしたら、どうなるか試してみたいですが、はっきり言って大変な作業なので、もういいやという気分です。
このソースを自分なりに解釈して、メインのフォーム(IndexMain)のEditに
"TO"と入力してEnterを押すと"自動"という表示に変わり
およそ1秒後にForm2(Dmaking?Pmaking?)が表示され
そのForm2にあるEditに約10秒間"Hellow"が点滅表示されてForm2は閉じる。
その後2回目はタイミングにより20秒から60秒後に表示され
3回目以降は約60秒後(タイミングによっては約40秒後)にForm2が表示され続ける。
という動作になりましたが、これでいいのでしょうか?
多分、1分おきにネット上のどこかに接続したいのでしょうけど
「ネット接続」と一口に言っても、いろいろな処理が考えられます。
取り敢えず、IdHTTPを使ってということなので
Form2にMemoとIdHTTPを追加して
procedure TPMaking.OnActivate(Sender: TObject);
var
n:integer;
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
try
IdHTTP1.Get('http://www.yahoo.co.jp',ms);
ms.Position := 0;
memo1.Lines.LoadFromStream(ms);
finally
ms.Free;
end; Dmaking;
PostMessage(Handle,WM_CLOSE,0,0);
end;
こんな風にしてみましたが、特にエラーは発生しません。
IdHTTPをどのように使うのか、さらにそれで得られた結果を
どう処理しているのかにポイントだと思います。
発生するエラーからして、どこかでSetFocusを呼んでいませんか?
そこがフォームが閉じられた後に実行されるとか。
デバッグオプションの「言語の例外で通知」にチェックをいれれば
エラーが発生する箇所を特定できるのでは?
あと、老婆心ながら
Making:=TPMaking.Create(Application);
Making.ShowModal;
Making.update;
この部分の最後のupdateってReleaseの間違いでは?
このままだと、作成したTPMakingフォームが開放されずに
どんどんメモリを食っていきます。
ありゃ、かぶった。
検証しなおしますが、エラー発生の前に
いくつも立ち上がるのは再現できませんでした。
Making.update;
これを
Making.Release;
にしたらどうですか?
Dmakingを
procedure TForm2.Ddmaking;
var
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
try
IdHTTP1.Get('http://www.yahoo.co.jp',ms);
ms.Position := 0;
memo1.Lines.LoadFromStream(ms);
finally
ms.Free;
end;
end;
この様にして
Form2にTimerを追加してそのOnTimerイベントで
procedure TForm2.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
Dmaking;
Sleep(2000); //直ぐに消えてしまうのを防ぐ
PostMessage(Handle,WM_CLOSE,0,0);
end;
こんな風にしましたけどエラーは出ませんね。
Form2.Timer1のIntervalは1000、EnabledはTrueです。
やはりネット接続自体がエラーの原因ではなく
その結果の処理中に起こるのだと思います。
Form2はどのタイミングでCloseしますか?
また、Form2がいくつも立ち上がるというのはForm2が複数同時に表示されるという意味ですよね。
少なくともアップされたソースでは同時表示されることはないです。
定期的に何度も表示されるのはプログラム通りですが。
複数表示されるのは
OnActiveでエラーが発生して
PostMessage(Handle,WM_CLOSE,0,0);
が実行されCLOSE されてない気がする
2009 -> XE2 で Indy のバージョン がわかって
影響が出てるのかも
Questさん、KHE00221さん、早速にありがとうございます。
ネットに接続するプログラムの中にエラーの原因があるかもというご指摘、研究させてもらいます。
setfocus使ってますし、またupdateの件もありがとうございます。
専門に研究してるわけではないので、意味分からずにupdateを使いまくってます。
Indyの件はその通りだと思います。ネット接続を自動でさせないような意図が感じられます。
やはり、だめでした。
正常に動作している(ネット接続しないで、Hellowを表示する)プログラムTrailにネットに接続するFormのFOnNetを組み込んで、現在はTimerを使っていないFOnNetをTimerを使ってネット接続プログラムPOnNetを作動させるようにしてコンパイルすると、できました。
ボタンを使ってFOnNetを立ち上げると、立ち上がってすぐ消えます。
プログラムミスを訂正して、FOnNetを立ち上げるとTimerですぐにPOnNetを立ち上げるようにすると、コンパイルできずにEInValidOperationエラーが出ました。
関係するすべてのFormのsetfocusを削除しても、このエラーが出ます。
あきらめて、最初からやりますために、すべての修正したFormを保存せずに終了して、projectからも削除して(Hellowを表示する)最初の状態に戻してコンパイルしても、このエラーが出ます。
次に、project名を変えると、このエラーはでなくなり、正常にHellowを表示するようになります。
以上のことからの推論です。
ネットに接続するPOnNetは、delphiに危険なプログラムであると認識されて、それを自動で接続しようとする(Timerを使う)プログラムはコンパイルできないようにされるんだと思います。
そして、それはproject名で記憶され、その名前のprojectは、内容に関係なくコンパイルできないようにされると思います。
ちょっと気になるのが、エラー表示が出たときブレークボタンを押すとプログラムの異常箇所に移動していたと思うんですが、XE2ではどうなんでしょうか。
このエラーのときはどこにも行かないんですけど。
Questさんへ、いろいろ書き込みしていただいているので、まとめて回答します。
1)IndexMainの動きはその通りです。
2)IdHTTP1.Get('http://www.yahoo.co.jp',ms);これだけでいいのですか。エラーなどはでませんか。私のは、サブルーチンを組んですごく複雑なんですけど。2009のときに書き換えたんですが。これが原因かも知れませんね。
3)setfocusの件は関係ありませんでした。
4)デバッグオプションの「言語の例外で通知」にチェックをいれれば
エラーが発生する箇所を特定できるのでは?
これは、やり方が分かりません。「表示」に「デバック」があるので、見てみましたが、よくわかりませんでした。
5)updateをreleaseに変えても異常はなおりませんでした。これは、知らないことだったので、すごく感謝しています。
6)Form2はPOnNetの作業が終わってから消してます。Form2がいくつも立ち上がるのは、POnNetが作業している途中に出ることが多いです。最初にまとめて何個も立ち上がることもありますが。
7)やはりネット接続自体がエラーの原因ではなくの件ですが、Questさんのプログラムは「危険」ではないからだと思います。いくらなんでもこれはだめだろうと自分で思えるプログラムで試してみてください。
いろいろとありがとうございました。
時間があればいろいろ試してみたいです。
今後もよろしくお願いします。
えーと、いくつかあるのですが、まず
>IdHTTP1.Get('http://www.yahoo.co.jp',ms);これだけでいいのですか。
とあるサイトのHTMLを取得するのはこれだけです。
もちろん、このままだと文字コードの問題などあるので後処理も必要ですが。
そもそもAsさんのおっしゃる「ネット接続」というのが具体的に何をするのか分かりませんので
とりあえずインターネットに接続してサーバーにあるデータを取ってくる動作として
このようにしただけです。
これ(IdHTTP1.Getだけ)でいいかどうかは、Asさんのなさりたい事によります。
「言語の例外で通知」はDelphiのメニュー「ツール」から「オプション」を選択し
左側のツリー表示の下のほうにある「デバッガオプション」の「Embarcaderoデバッガ」にある
「言語固有の例外」をクリックしてください。
で、右画面の下のほうに「言語の例外で通知(N)」というチェックボックスがあるので
これにチェックをいれます。
その上でデバッグ実行すれば、エラーが発生したときに停止するので
問題の箇所を特定できると思います。
ただし、try...exceptで処理している例外もすべて停止するので注意が必要です。
でも、コンパイル時にEInvalidOperationエラーが出るって、なんか変な感じがするけど?
ん?
いま読み返したら「エラー表示が出たときブレークボタンを押すと」ってありますね。
って事はすでにチェックを入れているのかな?
で、ブレークボタンでエラーの発生箇所に飛べないということは
ソースが管理下にない所でエラーが発生しているって事ですね。
Indyでエラーが出るなら、プロジェクトオプションの検索パスに
$(BDS)\source\Indy10 を追加すれば表示されるかも。
KHE00221さんのおっしゃる「Indy のバージョンがわかって影響が出てるのかも」っていうのは
動作に必要なパラメータとかが変更になって、うまく動かないんじゃないかということじゃないでしょうか。
「ネット接続を自動でさせない」という表現も、何を持って「自動で接続」なのかよく分かりませんが
URLを指定してGetメソッドを呼べば、ある意味自動でインターネットにアクセスしてくれます。
ノートンやマカフィなどのセキュリティソフトにブロックされる事はありますが
それは通信を許可するように設定すればすみますので。
少なくともIndy自体にファイヤーウォールのような機能は無いと思います。
あと、Delphiにも「これは危険なプログラムだから、コンパイルできなくしてやれ」なんて機能は無いですよ^^;
「危険」なプログラムって何でしょう?(^^ゞ
まさかDoS攻撃するとか、パスワード総当りするとかじゃないですよね。^^;
とあるサイトにいって、そこに表示(またはリンク)されているJPGファイルを根こそぎ自動で
ダウンロードしまくる(ブラウザーで画像に名前を付けて保存の動作を自動で繰り返す)アプリは
Indyで作ったことありますけど、こんなのは「危険」のうちに入らないですし(ですよね?>皆さん^^;)
やはり、これ以上は「ネット接続」とは具体的に何をどうしているのかが分からないと
検証するにも限界がありますね。
Trialで、二つのformにTimerを使って、ネット接続のプログラムを完璧に作動せることに成功しました。
何が原因かは全く分かりませんが。
手順としては、問題のないHellowを表示するProjectのIndexMainのOnTimerを削除してボタンでFOnNetを呼び出すようにしました。呼び出されたFOnNetでPOnNetの呼び出しのにTimerを使ってするようにプログラムしました。
これが完全に作動するすることを確認して、IndexMainにONTimerを組み込みました。
これが成功しました。
後は、本物に組み込めるかどうか試してみます。
Questさん、ネット接続プログラムが悪いのではないようですね。
ありがとうございました。
ツイート | ![]() |