コマンドボタンを押すと別なプログラムを開く
メニュープログラムがあるのですが
コマンドボタン?キーボードの上にノートなどの載せてしまい。
延々とプログラムを起動してしまいます。。
そのためプログラム起動毎にOracleの接続を行うので
一人のユーザーで全てのセッションを使用してしまい
システム全体が止まってしまったのですが。プログラム数が多すぎて
今から重複起動のソースを組み込む事はしたくないのですが?
メニューのプログラムから判定する事?歯止めすることできますか?
よく使い方がわからないけど、
App.PrevInstance
でうまく良くかも。
先輩が作ったので、、、、、、、
動いている事は動いてます。
App.PrevInstanceを全てのプログラムに入れる事が出来ないので
ここで質問させていただいたのです。
起動元から使えるんですか?
PrevInstanceは、自分のソフトが二回目以降の起動のとき(自分のソフトが二重起動しようとしているとき)にTrueになります。
事足りる場合はそれでいいんですけど、
この場合、ほかのソフトの重複起動抑止ということになるから、
それではだめなんじゃないですか?
えーと、そういう場合は、ボタンのMouseDownに、起動イベントを移動すればいいと思います。
けど、そのままではMouseDownが、押されっぱなしのときにも発生してしまうので、
一回目のMouseDownのときに何らかのフラグを立てて、二回目以降のMouseDownを遮断。
MouseUpのときにそのフラグを消せばいいです。
ただ、マウスを押しっぱなしにした状態で、キーボードのキーを押して、
そのままマウスをボタンの外に移動して、離したりすると、
たまにMouseUpが発生せず、フラグが立ったままになることがあります。
なので、Timerなどを使って、おかしいと思われるフラグは消すとか、
何か、いざというときのための処置が必要です。
メニューのプログラムからは既にいくつでも
プログラムの起動ができる仕様でメニューはいつでも落とす事ができるので
メニュー内でメモリ管理もしくは終了確認の判定?するといった事ができません
お願いします。
たかみちえさんありがとうございます
教えていただいた処理を使用すると?
Enterでのコマンドボタンを廃止?って事になるんでしょうか?
Clickイベント?確認してみないとわかりませんが?
キーボードでのボタン押下を破棄しないで可能でしょうか?すいません
横レス失礼します。
考えられる方法はいくつかあると思います。。
1.メニュー画面でコマンドボタン押した時点でAPIでプロセス上の
Windowタイトルを全て取得しこれから起動するプログラムのWindowタイトルと
バッティングしてるか判定して起動破棄?
(起動プログラム毎にCaptionを持つ為お勧めできませんし同一タイトルがいたらアウトです。)
2.コマンドボタンを押して別プログラムを起動した後に
押されたコマンドボタンを選択不可(Enabled = False)にして
APIでアクティブウィンドウのハンドルが押下時点(メニュープログラム)
のハンドル以外(起動したプログラム)に変更されるまで
同期のLoop内でDoeventsでイベント逃がしながら判定しつづける。
(フォーカス遷移が認められるまでって事です)ハンドル変更が確認できたら
ボタンを選択可能状態に戻す。(未確認ですができると思います)
3.OracleのDBAよりユーザー?その端末の人が何個セッションを使用しているか?取得して
一つの端末で使用できるセッション数に制限を付けちゃう。
五個以上Oracleセッションを使用していいたらプログラムの起動をキャンセルするみたいに。
(全てのプログラム起動に組み込むとパフォーマンスが落ちますが・・・)
※アクセスやその他プログラム?システム以外のセッションを覗く判定も必要になってしまいます。
※Oracleサーバー側のいくつかの制限が必要になってしまいます。
さわさん三つもの方法ありがとうございます。
降番2の方法を使用するのが良いのでしょうか?
試してみたいと思うのですが?初心者の為か解らない点があります。
アクティブウィンドウ、フォーカス遷移の判定をどうやったらいいんですか?
教えていただければうれしいです。お願いします。
>Enterでのコマンドボタンを廃止?って事になるんでしょうか?
>Clickイベント?確認してみないとわかりませんが?
まあ、とりあえずやってみてください(^^ゞ
Clickと、MouseDownは、同一のタイミングで起こります。
左クリックだけにしたいなら、引数として押されたボタンが渡されているので、
それが左クリックを示していない場合ははじくようにします。
Enterキーも入れたい場合は、KeyDownイベントで、Enterキーが押されたら、
MouseDownイベントを起こすようにすればいいだけです。
ところで、もうひとつ方法を思いつきました。面倒ですけど。
実行ファイルをCreateProcessというAPIを使って起動すると、
その引数として指定するProcessInfo構造体にプロセス情報が返ります。
それを、できるだけ早めに指定したタイマーで、
毎回その構造体が有効なものかを確かめます。
そして、構造体の内容が有効な間は、ボタンを押してもエラーを出すか、無反応にしておきます。
(このあたりはさわさんの言う、DoEventsにおきかえられるかもしれません、
もしできたら、あんまり変わりないことになりますけどね^^;)
あたしの上げた方法ですが試して見たところいくつか問題があったので
1.Enabledでボタン制御した時点で次のフォ-カスに遷移してしまうので
その部分の考慮が必要です
2.Enabledを廃止した場合Formにフォーカスを移動するとかの処理が必要です。。
↑を無視した場合↓の様になります
↓の関数は単純にForm上にコマンドボタンしかないメニューのイメージです。
コマンドボタンがいくつもプログラム起動とか戻る?終了?とかのイメージです
Public Declare Function GetActiveWindow _
Lib "user32" () As Long 'アクティブウィンドウのハンドル取得
Public Sub nfTest()
Dim lhWnd As Long 'Windowhwnd
Dim bExit As Boolean '同期LoopOutフラグ
Dim oCont As Object 'オブジェクトの参照用
On Error Resume Next 'エラースルー
'スレッド待機フラグを下ろす
bExit = False
'画面コントロール全てを検索
For nCnt = 0 To Screen.ActiveForm.Count - 1
'コマンドボタンのみ検出、Enabledメソッドを持つもの
If TypeOf Screen.ActiveForm.Controls(nCnt) Is CommandButton Then
'イベント通知の認識破棄
Screen.ActiveForm.Controls(nCnt).Enabled = False
End If
Next
'フラグが立つまで同期待機
Do Until bExit
'アクティブウィンドウのハンドル取得
lhWnd = GetActiveWindow
'当プロジャクトのアクティブフォームのハンドルとスレッド上のアクティブウィンドウハンドルが違う?
If Screen.ActiveForm.hWnd <> lhWnd Then
'スレッド待機フラグを立てる
bExit = True
End If
'イベントキューを逃がす
DoEvents
Loop
'イベント通知認識破棄のコマンドボタン全ての再起
For nCnt = 0 To Screen.ActiveForm.Count
If TypeOf Screen.ActiveForm.Controls(nCnt) Is CommandButton Then
Screen.ActiveForm.Controls(nCnt).Enabled = True
End If
Next
'エラークリア
Err.Clear
End Sub
プログラム起動後に↑の処理で待機させ
実行プログラムにフォーカス遷移しない場合(延々とEnterKeyによるClickイベントを拾ってる状態)待機しながらClickイベントを逃がしています。
Form上にコマンドボタン以外が存在する場合は追加する事になりますが
イメージとしては上記の様な感じでしょうか?
Form上にコマンドボタンをいくつか置いてCallして見れば解ると思います。
たいした問題ではないのですが?
↑のプロシージャでoContのオブジェクトが遊んでいます・・・
毎回コントロール配列の参照をするのではなく
Set oCont = Screen.ActiveForm.Controls(nCnt)
にした方が早いのかも?しれません。
あとScreen.ActiveFormもやめた方がいいかもしれません・・・
自分のFormを参照で渡しても同じ事です。
標準モジュールにいても呼べるって程度の問題です。
好まれるかどうかは私には判断しかねますけど。。
度々すいません。。
↑の2番のFormにフォーカス当てるのは駄目ですね・・・
別プログラム起動でNormalFocus?で起動したら自分に当てていまいますから
なので上のプロシージャなら起動プログラムにフォーカス移動するので大丈夫だと思います。
お客さんの要望でキーボードで呼べる方がと言う事なので
たかみちえさんの言われた方法で試してみたのですけど
Enterキーを拾う事が出来ませんでした?VB6では駄目なんでしょうか?
後その前におっしゃってたフラグを戻す?タイミングが難しく
戻らない時が発生して呼びたいのに呼べなくなってしまいました
勉強不足ですいません。わざわざ説明までしていただいたのに。
さわさんプロシージャまで用意してもらいありがとうございます
さっそく試してみます。
メニューの画面ですが単純にフォームにボタンが並んでるだけです
最初のメニューでボタンを押すと次のフォームにサブメニューでプログラム毎のボタン
といったかんじです。
ツイート | ![]() |