フォームの制御(最前面)をするには?


ローホ2号  2006-03-24 19:59:12  No: 130778

環境:WinXP、VB.NET
いつもお世話になっています。

選択されたテーブル(MDB)項目の内容をExcelのセルに入力する処理を初めて作成しました。
流れとしては入力処理終了後にExcelを表示(wApp.Visible=True)したら
そのまま閉じる(wApp.Quit)ことはせずにwApp,wBook…等を解放して終了。
あとはExcel側で名前を付けて保存するなり閉じるなり…といった感じです。
この時Excel画面はフォームの上に表示されExcel画面を閉じればフォーム
が最前面になるのかなというイメージだったんですがそうではなく
タスクバーでフォームを選択しないと前面に来ない状態です。
これを最前面にさせる方法はあるでしょうか?
そもそも何か思い違いをしてるかもしれませんがよろしくお願いします。


通ってみた  2006-03-25 08:16:19  No: 130779

APIのSetActiveWindowとか?


初心者ですが  2006-03-26 01:54:33  No: 130780

Excelに限らずWordとか外部アプリを起動して閉じた時に真下にあった
フォームが一瞬見えたあとにエクスプローラとか別ウィンドウが
立ち上がってるとしてそのうしろに隠れちゃうとか・・・って事ですか?

単純に最前面はTopMostプロパティをTrueだと思いますが
それだとExcelを表示してもフォームが上になっちゃうから
フォームがアクティブになったときにActivatedとかで
TopMost = True
TopMost = False
とかはダメでしょうか?


初心者ですが  2006-03-26 02:00:34  No: 130781

>フォームがアクティブになったときにActivatedとかで
外部アプリを閉じた時にうしろに隠れちゃうんだからActivatedイベントは
検出されないのかな・・?ダメっぽいですね。
やはり初心者ごときが回答するもんじゃないですね。忘れて下さいm(_ _)m


ローホ2号  2006-03-29 02:43:03  No: 130782

初心者ですがさんありがとうございます。
>フォームがアクティブになったときにActivatedとかで
念のため試してみましたが、ご想像の通りでした。

通ってみたさんありがとうございます。
>APIのSetActiveWindowとか?
APIの使用法がよく分からずまだきちんとは試せていません…すいません。
なにかサンプルコードのようなものはないか調査中です。

あとアクティブにするタイミングはアプリケーション(Excel)が終了したら
という事になると思い、ProcessクラスであればExitedイベントで終了を
検出できるという事までは調べたんですが…
元々今回は「セルにデータを入力する」が勉強課題で現在は下記のような
コードになっているのですが、終了を検出する方法はあるでしょうか?

    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) Handles Button1.Click

        '中略(テーブル接続等)

        '※テスト(テーブル内容をExcelのセルへ)
        If mDataTable.Rows.Count > 0 Then
            Dim i, j As Integer
            Dim wRowCnt As Integer = mDataTable.Rows.Count - 1
            Dim wColCnt As Integer = mDataTable.Columns.Count - 1
            Dim wSetItem(wColCnt) As String
            Dim wCol1, wCol2 As String
            '
            Dim wAppli As New Excel.Application
            Dim wBooks As Excel.Workbooks
            Dim wBook As Excel.Workbook
            Dim wSheets As Excel.Sheets
            Dim wSheet As Excel.Worksheet
            Dim wCells, wRange, wRange1 As Excel.Range
            '
            wBooks = wAppli.Workbooks
            wBook = wBooks.Add
            wSheets = wBook.Worksheets
            wSheet = CType(wSheets.Item(1), Excel.Worksheet)
            wCells = wSheet.Cells

            '配列にセット:見出し(フィールド名)
            For i = 0 To wColCnt
                wSetItem(i) = mDataTable.Columns(i).Caption
            Next

            '配列内容をExcelのセルへ
            wRange1 = CType(wCells(1, 1), Excel.Range)
            wCol1 = wRange1.Address(False, False)
            ReleaseComObj(CType(wRange1, Excel.Range))
            wRange1 = CType(wCells(1, wColCnt + 1), Excel.Range)
            wCol2 = wRange1.Address(False, False)
            wRange = wSheet.Range(wCol1 & ":" & wCol2)
            wRange.Value = wSetItem
            '
            ReleaseComObj(CType(wRange1, Excel.Range))
            ReleaseComObj(CType(wRange, Excel.Range))

            For i = 0 To wRowCnt
                '配列にセット:1レコード分(フィールド値)
                wSetItem.Initialize()
                For j = 0 To wColCnt
                    wSetItem(j) = mDataTable.Rows(i)(j).ToString
                Next

                '配列内容をExcelのセルへ
                wRange1 = CType(wCells(i + 2, 1), Excel.Range)
                wCol1 = wRange1.Address(False, False)
                ReleaseComObj(CType(wRange1, Excel.Range))
                wRange1 = CType(wCells(i + 2, wColCnt + 1), Excel.Range)
                wCol2 = wRange1.Address(False, False)
                wRange = wSheet.Range(wCol1 & ":" & wCol2)
                wRange.Value = wSetItem
                '
                ReleaseComObj(CType(wRange1, Excel.Range))
                ReleaseComObj(CType(wRange, Excel.Range))
            Next

            '表示
            wAppli.Visible = True

            ReleaseComObj(CType(wCells, Excel.Range))
            ReleaseComObj(CType(wSheet, Excel.Worksheet))
            ReleaseComObj(CType(wSheets, Excel.Worksheets))
            'wBook.Close(False)
            ReleaseComObj(CType(wBook, Excel.Workbook))
            ReleaseComObj(CType(wBooks, Excel.Workbooks))
            'wAppli.Quit()
            ReleaseComObj(CType(wAppli, Excel.Application))
            '
        Else
            MessageBox.Show("該当データなし!")
        End If
    End Sub


んー  2006-03-29 07:50:46  No: 130783

やろうと思えば今ある知識(↑)だけでも何とかなるのでは?

[入力後のファイルを保存]
Dim wPath As String = 保存ファイル名
wAppli.DisplayAlerts = False
wSheet.SaveAs(wPath)
wAppli.DisplayAlerts = True

[Process.Startメソッドで起動]
Process.Start("Excel.exe", wPath)

とか。
まぁそれなりの仕様もあるだろうし、あくまでそれっぽく動くのでは?
程度のものでとてもいい手法とは言えないけどね。
いずれにせよ質問に沿ったコードを載せた方が良いよ。
↑だと、あれっ?このスレ「Excelにデータを吐くには」だっけ?て感じが・・・


Tips  2006-03-29 15:29:31  No: 130784

こちらのサイトのTipsにありましたがどうですか?

<  SAMPLE  >
'標準モジュール
Public Declare Function SetActiveWindow Lib"USER32" (ByVal hWnd&) As Long
'ここからはフォームの処理
Private Sub Command1_Click()
     Dim Ret As Long
        ’Form1をアクティブにする
          Ret=SetActiveWindow(Form1.hwnd)
End Sub


参考  2006-03-29 17:59:01  No: 130785

SetActiveWindowの(古い)MSDN
> この関数は、アプリケーションがバックグラウンドにあるときには (現在ユーザーがほかのアプリケーションで作業をしているときには) 、ウィンドウをアクティブ化しません
また代用品としてSetForegroundWindowなどがありますが、Win2k(?)あたりからWin9xと挙動が違います。

他にもSetWindowPosなどもあります


ローホ2号  2006-03-31 05:22:56  No: 130786

返事が遅れてすいません。皆様アドバイスありがとうございます。

んーさん回答有難うございます。
ご指摘の通りだなと思います。今回はExcelを起動し新規ファイルを開きデータを入力したら
>あとはExcel側で名前を付けて保存するなり閉じるなり…といった感じです。
つもりでしたので保存処理は入れませんでした。Excel表示後、加工するのか
しないのか、保存するのかしないのか…etc 全てその時の判断で自由にと。
ですがこの方法であればたしかに終了時にフォームを前面にすることも
できそうなので今の自分等にはいい方法だと思うのでやってみます。

Tipsさん、参考さん回答有難うございます。
いくつかのサンプルや社内でAPI関連の技本など見つけましたがVB6の頃の
もので.NETから始めた初級者チームなので.NETに置き換えて参考にするといった
ことが全くの未熟だということが正直なところです。ヘルプ等もですが…
ですがいい機会なので色々勉強してものにできればと思います。

また遅れてしまうかもしれませんが結果報告できれば書込みします。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加