C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[7]: 別のWinアプリをモーダル表示したい


(過去ログ 98 を表示中)

[トピック内 17 記事 (1 - 17 表示)]  << 0 >>

■58712 / inTopicNo.1)  別のWinアプリをモーダル表示したい
  
□投稿者/ ブーマー (1回)-(2011/04/23(Sat) 20:23:53)

分類:[VB.NET/VB2005 以降] 

今作成しているWinアプリより、以下のようにして別のWinアプリを呼び出し、
そのアプリでの処理が終わったら元のWinアプリに戻るようなものを作成しようとしています。

Dim p As System.Diagnostics.Process
Dim psi As New ProcessStartInfo(起動するWinアプリ)
psi.WindowStyle = ProcessWindowStyle.Normal
psi.Arguments = コマンドライン引数
p = Process.Start(psi)
p.WaitForExit()
Dim intRet As Integer = p.ExitCode

そこで教えて頂きたいのですが、別のWinアプリが開いている間は元のWinアプリを操作できないことを意図的に示すため、
別のWinアプリを元のWinアプリのモーダルフォームのように起動することは可能でしょうか?
引用返信 編集キー/
■58713 / inTopicNo.2)  Re[1]: 別のWinアプリをモーダル表示したい
□投稿者/ Azulean (733回)-(2011/04/23(Sat) 21:42:13)
No58712 (ブーマー さん) に返信
> そこで教えて頂きたいのですが、別のWinアプリが開いている間は元のWinアプリを操作できないことを意図的に示すため、
> 別のWinアプリを元のWinアプリのモーダルフォームのように起動することは可能でしょうか?

「モーダルフォーム」に求めている、「意図的に示す」という状態は、元のアプリケーションをクリックしたときに、音が鳴った上で、別のアプリケーションがアクティブになるといるということですか?

そこまで凝らない方がよいような気がしているのですが、どうしても必要であれば、起動するときにウィンドウハンドルを渡して、そのウィンドウハンドルをオーナーとしたウィンドウを表示するように実装することでしょうか。
その起動する別アプリが修正不可能な場合は、もっと無理矢理になりそうですが…。
引用返信 編集キー/
■58716 / inTopicNo.3)  Re[2]: 別のWinアプリをモーダル表示したい
□投稿者/ ブーマー (2回)-(2011/04/24(Sun) 14:55:34)
No58713 (Azulean さん) に返信

ご回答ありがとうございました。
元のアプリから呼び出された別のアプリが開いている間は、元のアプリを操作できないようにしたいと考えていますが、
どちらにしろ、元のアプリは呼び出したアプリが終了するまで待機していますので、それならモーダルの関係であれば
呼び出したアプリが終了するまでは呼び出し元にアクセスができないだろうと考えた次第です。

呼び出すアプリは本来は単独で動作するものなので、dll化は考えていないのですが、こちらのアプリも修正できますので、
Azulean様のご提案の方法を試してみたいのですが、ウィンドウハンドルとか色々と分からないことがあります。

1.呼び出すアプリのコマンドライン引数にウィンドウハンドルを渡せばいいと考えていますが、これは、該当するフォームの
  Me.Handleの内容を利用すればよいのでしょうか?
  ただ、この型IntPtrを渡す場合、これを整数(Int32あたり?)にして渡せばいいのでしょうか?

2.呼び出されたアプリが受け取ったコマンドライン引数をどのようにすれば、呼び出し元のフォームをオーナーとしたフォームとして
  開くことができるでしょうか?
引用返信 編集キー/
■58717 / inTopicNo.4)  Re[3]: 別のWinアプリをモーダル表示したい
□投稿者/ Azulean (734回)-(2011/04/24(Sun) 17:29:33)
No58716 (ブーマー さん) に返信
> 元のアプリから呼び出された別のアプリが開いている間は、元のアプリを操作できないようにしたいと考えていますが、

そもそも、WaitForExit で待機しているわけですから、操作不能ですよね?
呼び出し元にアクセスできない状態は実現されているのでは?
今がどのような状態で、それからどうしたいのかを明確にしてください。

>   ただ、この型IntPtrを渡す場合、これを整数(Int32あたり?)にして渡せばいいのでしょうか?

整数にせざる得ないでしょう。

> 2.呼び出されたアプリが受け取ったコマンドライン引数をどのようにすれば、呼び出し元のフォームをオーナーとしたフォームとして
>   開くことができるでしょうか?

API 使わないといけないと思われます。
引用返信 編集キー/
■58720 / inTopicNo.5)  Re[4]: 別のWinアプリをモーダル表示したい
□投稿者/ ブーマー (3回)-(2011/04/24(Sun) 19:17:30)
No58717 (Azulean さん) に返信

> そもそも、WaitForExit で待機しているわけですから、操作不能ですよね?
> 呼び出し元にアクセスできない状態は実現されているのでは?
> 今がどのような状態で、それからどうしたいのかを明確にしてください。

ただ単にアクセスできない状態でも、呼び出し元のフォームはアクティブになってしまいます。
これでは、呼び出したアプリのフォームとの関連がユーザーに分からなければ、ユーザは、
なぜアクティブになったフォームにアクセスできないのか、場合によってはソフトがハングアップしたと
勘違いしてしまうのではないでしょうか?
だから、各々のアプリの関連をユーザに分かるようにすべきだと考えます。
そこで、モーダルであれば、親フォームをアクティブにしようとすると、必ずモーダルフォームが前面に出てきます。
このような状態であれば、呼び出したアプリを操作しなければ、元の画面に戻らないということが明確にユーザに
示すことができると考えます。

> API 使わないといけないと思われます。

それを具体的に教えて頂きたいのです。
引用返信 編集キー/
■58724 / inTopicNo.6)  Re[5]: 別のWinアプリをモーダル表示したい
□投稿者/ とっちゃん (568回)-(2011/04/24(Sun) 21:37:21)
とっちゃん さんの Web サイト
No58720 (ブーマー さん) に返信
> ただ単にアクセスできない状態でも、呼び出し元のフォームはアクティブになってしまいます。
アクティブになるのではなく、アクティブになっているように見えるではありませんか?

ところで、呼び出し先は、.NET を使っている?
もしそうなら、EXEとして呼び出さずにDLLとして呼び出せばいいのでは?

これなら、普通にクラスライブラリを作ってそれを呼び出すのと全く同じ手段で
ウィンドウを操作できますよ。

引用返信 編集キー/
■58725 / inTopicNo.7)  Re[6]: 別のWinアプリをモーダル表示したい
□投稿者/ ブーマー (4回)-(2011/04/24(Sun) 22:02:42)
No58724 (とっちゃん さん) に返信
> ところで、呼び出し先は、.NET を使っている?
> もしそうなら、EXEとして呼び出さずにDLLとして呼び出せばいいのでは?

はい、dllで呼び出せばこのような面倒なことを考える必要はないのですが、
58716に記載の通り、dll化は考えておりません。
(これは諸般の事情のためということでご理解ください。)

なので、APIを使用してでも呼び出すexeをモーダル(疑似モーダル?)な感じにしたいのです。
引用返信 編集キー/
■58726 / inTopicNo.8)  Re[7]: 別のWinアプリをモーダル表示したい
□投稿者/ とっちゃん (569回)-(2011/04/24(Sun) 22:45:52)
とっちゃん さんの Web サイト
No58725 (ブーマー さん) に返信
> ■No58724 (とっちゃん さん) に返信
>>ところで、呼び出し先は、.NET を使っている?
>>もしそうなら、EXEとして呼び出さずにDLLとして呼び出せばいいのでは?
>
> はい、dllで呼び出せばこのような面倒なことを考える必要はないのですが、
> 58716に記載の通り、dll化は考えておりません。
> (これは諸般の事情のためということでご理解ください。)
>
DLLにするのではありません。.NET アプリであればEXEのままでもDLLとして参照することができます。

その方法を使って呼び出します。呼び出される側のプロジェクトは今のまま何も変更せずに対応できます。
引用返信 編集キー/
■58727 / inTopicNo.9)  Re[8]: 別のWinアプリをモーダル表示したい
□投稿者/ ブーマー (5回)-(2011/04/24(Sun) 22:59:16)
No58726 (とっちゃん さん) に返信

> DLLにするのではありません。.NET アプリであればEXEのままでもDLLとして参照することができます。
>
> その方法を使って呼び出します。呼び出される側のプロジェクトは今のまま何も変更せずに対応できます。

ところで、この場合、DLLとして呼び出すEXEは呼び出し元のアプリと別のプロセスとして動作することは可能ですか?
別のプロセスでなければならないという諸般の事情で、dll化を行えませんでしたので。
引用返信 編集キー/
■58728 / inTopicNo.10)  Re[9]: 別のWinアプリをモーダル表示したい
□投稿者/ とっちゃん (570回)-(2011/04/24(Sun) 23:09:07)
とっちゃん さんの Web サイト
No58727 (ブーマー さん) に返信
> ■No58726 (とっちゃん さん) に返信
>
>>DLLにするのではありません。.NET アプリであればEXEのままでもDLLとして参照することができます。
>>
>>その方法を使って呼び出します。呼び出される側のプロジェクトは今のまま何も変更せずに対応できます。
>
> ところで、この場合、DLLとして呼び出すEXEは呼び出し元のアプリと別のプロセスとして動作することは可能ですか?
> 別のプロセスでなければならないという諸般の事情で、dll化を行えませんでしたので。

DLLとして呼び出した場合はそのプロセス内で動くので同一プロセスで動きます。
ですが、単体で実行すれば別のプロセスでどうさせることができます。

それではだめなのでしょうか?

引用返信 編集キー/
■58729 / inTopicNo.11)  Re[10]: 別のWinアプリをモーダル表示したい
□投稿者/ ブーマー (6回)-(2011/04/24(Sun) 23:26:05)
No58728 (とっちゃん さん) に返信

> DLLとして呼び出した場合はそのプロセス内で動くので同一プロセスで動きます。
> ですが、単体で実行すれば別のプロセスでどうさせることができます。
>
> それではだめなのでしょうか?
>

この別のプロセスとして呼び出したアプリを、呼び出し元に対してモーダル表示することは可能かという質問をするために
このスレッドを立てています。
引用返信 編集キー/
■58731 / inTopicNo.12)  Re[5]: 別のWinアプリをモーダル表示したい
□投稿者/ Azulean (735回)-(2011/04/25(Mon) 00:32:37)
よく考えれば、API など使わなくても良さそうな気はしますが、いきなりモーダル表示すると、それはそれでめんどくさいかもしれないなぁと思っています。

No58720 (ブーマー さん) に返信
> それを具体的に教えて頂きたいのです。

ShowDialog の引数に渡すものは何か、それは何を返すものかを調べれば見えてきませんか。
そのインターフェースを実装するクラスは自作してください。

VB.NET のコードは書けなくもないと思っていますが、調べる過程を身につけてほしいので具体的なコードは書きません。
調べた上でわからなかった場合は、何を調べ、何を理解し、何が理解できなかったかを明示してください。


No58729 (ブーマー さん) に返信
> この別のプロセスとして呼び出したアプリを、呼び出し元に対してモーダル表示することは可能かという質問をするために
> このスレッドを立てています。

プロセス間で連携して動くのはいろいろと面倒なことがあります。
スレッドで分けるでもなく、本当に別プロセスでなければならない事情を抱えていると解釈してよいのでしょうか。

一般的なやり方とは言いがたく、また、困難な道を進もうとされているので、それを心配されているのだと私は思っています。
「最初からこう聞いているから」で終わらせるのではなく、事情を書くなり、事情が書けないなら書けないなりにもう少し返し方を変えても良いのかなとも思います。
引用返信 編集キー/
■58732 / inTopicNo.13)  Re[11]: 別のWinアプリをモーダル表示したい
□投稿者/ とっちゃん (571回)-(2011/04/25(Mon) 01:06:32)
とっちゃん さんの Web サイト
No58729 (ブーマー さん) に返信
> ■No58728 (とっちゃん さん) に返信
>
>>DLLとして呼び出した場合はそのプロセス内で動くので同一プロセスで動きます。
>>ですが、単体で実行すれば別のプロセスでどうさせることができます。
>>
>>それではだめなのでしょうか?
>>
>
> この別のプロセスとして呼び出したアプリを、呼び出し元に対してモーダル表示することは可能かという質問をするために
> このスレッドを立てています。

現在のまま一切改変することなくDLLとして呼び出せるけどそれではだめということなんですね。

であれば、アクティブになるのがいやということなので、呼び出すときに自分自身を非表示(Hide)にすればいいのでは?
それなら、今のままで、WaitFor の直前で Hideにして、直後に Showすれば問題ないと思いますよ。

消えるのはダメ。という場合は非アクティブな状況でどの程度反応できる必要があるかを明示してください。
今のままでいいとしたら非表示にしない理由を明示してください。なにせ、表示していることが無意味な状態なので
そこから理由を導き出せない。。。

引用返信 編集キー/
■58740 / inTopicNo.14)  Re[6]: 別のWinアプリをモーダル表示したい
□投稿者/ ブーマー (7回)-(2011/04/25(Mon) 11:30:11)
No58731 (Azulean さん) に返信
> ShowDialog の引数に渡すものは何か、それは何を返すものかを調べれば見えてきませんか。
> そのインターフェースを実装するクラスは自作してください。

ヒントありがとうございます。
ShowDialogの引数の型を見てみると、IWin32Windowというインタフェースを実装したものとのことですが、
とりあえず、この引数にオーナーとなるフォームを設定するということまでは理解できました。
(認識に誤りがありましたらご指摘ください。)
おそらく、通常の使い方としては、Form1をオーナーとしたForm2のダイアログを呼び出すときに、

Form2.ShowDialog(Form1)

とすれば、オーナーをForm1としたダイアログを開くと理解しました。
(ただし、今まではForm1上からForm2のダイアログを開くときに、Form2.ShowDialog(Me)のように
引数をつけたことはありませんでした。当方はこの分野の専門家ではありませんので、この程度の
初歩的なスキルしか持ち合わせていないと思って頂ければ結構です。)

最終的には、ShowDialogの引数に、元アプリの画面のハンドルを持ったフォーム的なものを与えればいいのだと思いますが、
それをどうすればいいのかさっぱり分かりません。
例えば、ハンドルからどうやってこのフォーム的なものを作ればいいか分かりません。
(単に、IWin32Windowを実装したクラスを適当に作成して、そのハンドルに元アプリの画面のハンドルを渡せばいいのでしょうか?)
何か、ヒントになるサイトはありますでしょうか?
引用返信 編集キー/
■58743 / inTopicNo.15)  Re[12]: 別のWinアプリをモーダル表示したい
□投稿者/ ブーマー (8回)-(2011/04/25(Mon) 12:38:31)
No58732 (とっちゃん さん) に返信
> であれば、アクティブになるのがいやということなので、呼び出すときに自分自身を非表示(Hide)にすればいいのでは?

そうですね。自分自身を非表示にすれば、アクティブうんぬんを考慮する必要はないですね。
ただし、呼び出し元がMDI形式の子フォームなので、そうなるとMDI親フォームを非表示にする必要があり、
何だかかっこ悪いと感じました。
(技術的な知識はほとんどないので、見た目の見解しかできませんが、その点はご了承ください。)
引用返信 編集キー/
■58744 / inTopicNo.16)  Re[13]: 別のWinアプリをモーダル表示したい
□投稿者/ とっちゃん (572回)-(2011/04/25(Mon) 14:17:49)
とっちゃん さんの Web サイト
No58743 (ブーマー さん) に返信
> ■No58732 (とっちゃん さん) に返信
>>であれば、アクティブになるのがいやということなので、呼び出すときに自分自身を非表示(Hide)にすればいいのでは?
>
> そうですね。自分自身を非表示にすれば、アクティブうんぬんを考慮する必要はないですね。
> ただし、呼び出し元がMDI形式の子フォームなので、そうなるとMDI親フォームを非表示にする必要があり、
> 何だかかっこ悪いと感じました。
> (技術的な知識はほとんどないので、見た目の見解しかできませんが、その点はご了承ください。)

見た目の問題は重要です。

掲示板などでは、アプリケーションの挙動の細部にまで踏み込んでやり取りすることはめったにありませんが(たいていの場合そういうところは仕様書と呼ばれる類のものに記載されているので)、利用者にとっては、アプリケーションの内部的な仕組みやどうやって動いているのか?というのは、利用する上で必要な知識ではありませんし、通常興味を持ちません。
ですが、使い勝手はそうではなく、右利きの人が左利き用のはさみを使うのが非常に使いにくいのと同様、アプリケーションにも使いやすさ、使いにくさがあります。それらは利用者にとってみれば、場合によっては死活問題(左利き用のはさみを使っていて操作を誤ってけがをした。。。など)と呼べるほどに重要な要素であるといえます。

なので、決してないがしろにしてはいけませんし、かっこよさも求めていいと思います。かっこ悪いアプリはたいてい使いにくいですからね。

さて、本題。
今回の場合、呼び出し元の挙動をどうするか?という部分です。
アプリを呼び出している間(これについては、別プロセスで動くことが必須条件らしいのでそれを外さないという形で実現を考えましょう)反応しないことが問題でこのスレッドがあるのだと思います。
現在の状態は別アプリ呼び出し中に「マウスクリックしたりすると中が白くなってキャプションに「(応答なし)」と出てしまう状態」になってしまうと思います。

で、提示した一つの回避策が 58732 の隠してしまうという方法。実装が容易(現在の実装に2行たすだけ)で、要件は満たせているのですが、「かっこ悪い」と一蹴されたのでこれはなし。

ということで、次は画面を見せたまま上記の応答なしにならない方法を考えていくことになります。

まずは、なぜ応答なしになるのか?。。。なんて始めているときりがないので、応答なしについてはC++の記事ですがCodezineに書いてるのでそちらをご参照ください(私のブログの左側にリンクがあります)。
VBやC#でも、プログラムの書き方が違うだけで現象が起こる原因やその解決策そのものの内部的な実装は同じです(でもC#やVB使いにとっては、APIを使うというのは最後手段なのでそれに頼らない解決策を考慮する必要があります)。
これを理解しなければ。。。ということはありませんが、頭の片隅にでもあるのとそうではないのとでは全然変わってくるので、覚えておいて損はないと思います。

ということで、ここから先は現在の状況をもう少し細かく知る必要があります。
まずは、アプリは両方とも手を入れることができるということだったので、何らかのプロセス間通信をすでに導入しているか?を聞きたいと思います。
もし、すでにプロセス間通信を行っているのであれば、その機能を拡張して、ウィンドウを有効化・無効化するという段取りを組み入れることをお勧めします。
そうではない場合は、また考えてみたいと思いますが。。。


引用返信 編集キー/
■58754 / inTopicNo.17)  Re[7]: 別のWinアプリをモーダル表示したい
□投稿者/ ブーマー (9回)-(2011/04/25(Mon) 20:42:58)
結局、

> (単に、IWin32Windowを実装したクラスを適当に作成して、そのハンドルに元アプリの画面のハンドルを渡せばいいのでしょうか?)

の考えで、呼び出しアプリが元フォームのモーダルにすることができました。
具体的には、呼び出し先でIWin32Window.Handleを実装したクラスを作成し、このインスタンスに呼び出し元フォームのHandleを渡し、
呼び出し先のSub MainでモーダルにするダイアログをShowDialogするときに、このインスタンスを引数にすることで実現できました。
これで、望み通りのモーダル(偽装?)は出来ましたが、あとは呼び出しアプリ終了待機中を別スレッドにするなんてことも
勉強してみようと思います。
色々とありがとうございました。
このスレッドはこれにて終了とさせて頂きます。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -