tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルExcelの最大化・最小化ボタン
記事No10003
投稿日: 2010/03/17(Wed) 11:59
投稿者はる
いつも参考にさせていただいてます。

今回VB.netからExcelを制御するシステムを作っています。
VB.NET2008です。
Excelはレイトバインディングで制御します。

そこでCreateObjectしたExcelの最大化、最小化ボタンを非表示にしたいのですが、
WindowsAPIを使用するサンプルを見つけたので実装してみたところ
非表示になりません。

以下コード

   'APIの宣言
    'ウィンドウハンドルを取得する関数
    Public Declare Function FindWindow Lib "user32" _
           Alias "FindWindowA" (ByVal lpClassName As String _
                        , ByVal lpWindowName As String) As Long

    'ウィンドウに関する情報を返す関数
    Public Declare Function GetWindowLong Lib "user32" _
                 Alias "GetWindowLongA" (ByVal hWnd As Long _
                                   , ByVal nIndex As Long) As Long


    'ウィンドウの属性を変更する関数
    Public Declare Function SetWindowLong Lib "user32" _
                      Alias "SetWindowLongA" (ByVal hWnd As Long _
            , ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

    'メニューバーを描画する関数
    Public Declare Function DrawMenuBar Lib "user32" _
                                               (ByVal hWnd As Long) As Long


    '最大化ボタン
    Public Const WS_MAXIMIZEBOX As Long = &H10000

    '最小化ボタン
    Public Const WS_MINIMIZEBOX As Long = &H20000

    'スタイルを取得する定数
    Public Const GWL_STYLE As Long = -16&

   '非表示用のコード
    Sub BoxHide()
        Dim hWnd As Long
        Dim lngWstyle As Long

        'Excelのハンドル
        hWnd = FindWindow("XLMAIN", xlApp.Caption)

        '最小化・最大化ボタンの消去
        lngWstyle = GetWindowLong(hWnd, GWL_STYLE)

        SetWindowLong(hWnd, GWL_STYLE, lngWstyle _
             And (Not WS_MAXIMIZEBOX) And (Not WS_MINIMIZEBOX))

        'メニュー表示し直し
        DrawMenuBar(hWnd)

    End Sub

上記のメソッドを

               Dim xlApp as Object = CreateObject("Excel.Application")
               Dim xlBooks as Object  = xlApp.Workbooks

                '既存のファイルを開く場合
                Dim xlBook as Object  = xlBooks.Open(xlFilePath)
                Dim xlSheets as Object  = xlBook.Worksheets
                Dim xlSheet as Object  = xlSheets.Item(1)
                xlApp.WindowState = xlNormal
                xlApp.Left = Me.Left
                xlApp.Top = (Me.Top + Me.Height) * 0.75
                xlApp.Width = Me.Width * 0.75
                xlApp.Visible = True        'Excelを表示(必ずとも表示しなくてもよい)
                BoxHide()
と一番最後に呼び出しています。

Excelのウィンドウハンドルにも値が入ってきているのですが、
表示されたExcelには最大化、最小化ボタンがついたままです。

本当にやりたいことは最大化、最小化ボタンの非表示ではなく
Excelのウィンドウのサイズをユーザーが変更できないようにしたいのですが、
その方法が見つからず、とりあえず最大化、最小化の非表示だけでもと思っています。
一番いいのはサイズ固定、またはウィンドウのサイズが変更されたイベントを拾って
サイズを戻すことなのですが。。
Excelの中のActiveWindowでは求めていることができたのですが、
Excelそのもののウィンドウがどうにもできない状態です。

ぜひご指示、ご指摘お願いいたします。

[ツリー表示へ]
タイトルRe: Excelの最大化・最小化ボタン
記事No10004
投稿日: 2010/03/17(Wed) 12:25
投稿者花ちゃん
> 今回VB.netからExcelを制御するシステムを作っています。
> VB.NET2008です。
VB2008 で間違いないのですね。(コードが殆ど、VB6.0 のようなので)

Excel のバージョンや OS のバージョンも書くようにして下さい。

>    'APIの宣言
>     'ウィンドウハンドルを取得する関数
>     Public Declare Function FindWindow Lib "user32" _
>            Alias "FindWindowA" (ByVal lpClassName As String _
>                         , ByVal lpWindowName As String) As Long

VB6.0 用の宣言になっています。 VB2008 等では、変数の等の型が違います。
http://msdn.microsoft.com/ja-jp/library/dd297710.aspx
http://hanatyan.sakura.ne.jp/freesoft/win32api.htm

>                Dim xlApp as Object = CreateObject("Excel.Application")
>                Dim xlBooks as Object  = xlApp.Workbooks
>
>                 '既存のファイルを開く場合
>                 Dim xlBook as Object  = xlBooks.Open(xlFilePath)
>                 Dim xlSheets as Object  = xlBook.Worksheets
>                 Dim xlSheet as Object  = xlSheets.Item(1)
>                 xlApp.WindowState = xlNormal

Excel の操作に関しても、.NET 系では少し扱いが変わってきています。
http://hanatyan.sakura.ne.jp/dotnet/Excelflm.htm

まずは、上記の基本的な事からやり直して(プログラムを)下さい。

[ツリー表示へ]
タイトルRe^2: Excelの最大化・最小化ボタン
記事No10005
投稿日: 2010/03/17(Wed) 13:08
投稿者はる
> > 今回VB.netからExcelを制御するシステムを作っています。
> > VB.NET2008です。
> VB2008 で間違いないのですね。(コードが殆ど、VB6.0 のようなので)

VB2008です。

> Excel のバージョンや OS のバージョンも書くようにして下さい。

OSはWidowsXPですが、Windows7にも対応したいと思っています。
Excelは2003と2007が対象ですが、
バージョンに依存されたくないので、レイトバインディングで実装しています。


> VB6.0 用の宣言になっています。 VB2008 等では、変数の等の型が違います。
> http://msdn.microsoft.com/ja-jp/library/dd297710.aspx
> http://hanatyan.sakura.ne.jp/freesoft/win32api.htm

Long型の部分がIntegerに変わるだけだと思っています。
.NET用にAPI関数を書き換えるサイトで変更してみたのですが、
Long型がInteger型に変わっただけでした。
引数や戻り値の方が違うだけで動作が変わってくるものでしょうか?
IntegerとLongはサイズの違いだけですよね?

>
> >                Dim xlApp as Object = CreateObject("Excel.Application")
> >                Dim xlBooks as Object  = xlApp.Workbooks
> >
> >                 '既存のファイルを開く場合
> >                 Dim xlBook as Object  = xlBooks.Open(xlFilePath)
> >                 Dim xlSheets as Object  = xlBook.Worksheets
> >                 Dim xlSheet as Object  = xlSheets.Item(1)
> >                 xlApp.WindowState = xlNormal
>
> Excel の操作に関しても、.NET 系では少し扱いが変わってきています。
> http://hanatyan.sakura.ne.jp/dotnet/Excelflm.htm

参考URLとしてリンクを貼られた箇所を参考にして作っています。
上記も参考URLの「既存ファイルを開く場合」をコピーさせていただいたので
まったく同じコードで、Excelのオブジェクトの箇所をObjectに書き換えただけです。

以上、よろしくお願いします。

[ツリー表示へ]
タイトルRe^3: Excelの最大化・最小化ボタン
記事No10006
投稿日: 2010/03/17(Wed) 13:24
投稿者はる
すみません!!!

色々勘違いしていたみたいです!!!

今再度やり直しています。

おそらく今度はちゃんと動作確認できると思うので、
その後レスします!

[ツリー表示へ]
タイトルRe^3: Excelの最大化・最小化ボタン
記事No10007
投稿日: 2010/03/17(Wed) 13:45
投稿者はる
できました!
花ちゃんさんのご指摘どおり、VB.NET用にAPI関数を変換していなかったからでした。
ご指摘ありがとうございました!

以下、修正したコードです。

    'ウィンドウハンドルを取得する関数
    <System.Runtime.InteropServices.DllImport("user32.dll", CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
   Shared Function FindWindow( _
       ByVal lpClassName As String, _
       ByVal lpWindowName As String) As IntPtr
    End Function

    'ウィンドウに関する情報を返す関数
    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
    Public Shared Function GetWindowLong(ByVal hWnd As Integer, ByVal nIndex As Integer) As Integer
    End Function

    'ウィンドウの属性を変更する関数
    <DllImport("user32.dll")> _
   Private Shared Function SetWindowLong( _
        ByVal hWnd As IntPtr, _
        ByVal nIndex As Integer, _
        ByVal dwNewLong As IntPtr) As Integer
    End Function

    'メニューバーを描画する関数
    <DllImport("user32.dll")> _
    Shared Function DrawMenuBar(ByVal hwnd As IntPtr) As Boolean
    End Function

    '最大化ボタン
    Public Const WS_MAXIMIZEBOX As Integer = &H10000

    '最小化ボタン
    Public Const WS_MINIMIZEBOX As Integer = &H20000

    'スタイルを取得する定数
    Public Const GWL_STYLE As Integer = -16

    '非表示用のコード
    Public Shared Sub BoxHide(ByVal sAppCaption As String)

        'Excelのハンドル
        Dim hWnd As IntPtr = FindWindow(Nothing, sAppCaption)

        '最小化・最大化ボタンの消去
        Dim wStyle As Integer = GetWindowLong(hWnd, GWL_STYLE)

        SetWindowLong(hWnd, GWL_STYLE, wStyle And (Not WS_MAXIMIZEBOX) And (Not WS_MINIMIZEBOX))

        'メニュー表示し直し
        DrawMenuBar(hWnd)

    End Sub

解決です。
本当にありがとうございました。

ちなみにサイズの固定はできないですよね〜?

[ツリー表示へ]
タイトルRe^4: Excelの最大化・最小化ボタン
記事No10008
投稿日: 2010/03/17(Wed) 15:44
投稿者魔界の仮面弁士
>    Private Shared Function SetWindowLong( _
>         ByVal hWnd As IntPtr, _
こちらでは、ウィンドウハンドルを IntPtr 型で渡しているのに、

> Public Shared Function GetWindowLong(ByVal hWnd As Integer, ByVal nIndex As Integer) As Integer
こちらでは IntPtr にせず、Integer にしているのは何故でしょうか?


>  Dim hWnd As IntPtr = FindWindow(Nothing, sAppCaption)
Excel のウィンドウであれば、API を使わずとも xlApp.Hwnd で取得できますよ。


> 解決です。
タイトルバーのダブルクリックは大丈夫ですね?


> ちなみにサイズの固定はできないですよね〜?
WS_THICKFRAME や WS_SIZEBOX も切ってしまえば良いかと。

[ツリー表示へ]
タイトルRe^5: Excelの最大化・最小化ボタン
記事No10010
投稿日: 2010/03/18(Thu) 09:47
投稿者はる
> >    Private Shared Function SetWindowLong( _
> >         ByVal hWnd As IntPtr, _
> こちらでは、ウィンドウハンドルを IntPtr 型で渡しているのに、
>
> > Public Shared Function GetWindowLong(ByVal hWnd As Integer, ByVal nIndex As Integer) As Integer
> こちらでは IntPtr にせず、Integer にしているのは何故でしょうか?

何も気にせずにGetWindowLongを.NET用に変換したものをネットで見つけてきて
使っていました。。ご指摘ありがとうございます。

> >  Dim hWnd As IntPtr = FindWindow(Nothing, sAppCaption)
> Excel のウィンドウであれば、API を使わずとも xlApp.Hwnd で取得できますよ。

そうなんですか!知りませんでした。

>
> > 解決です。
> タイトルバーのダブルクリックは大丈夫ですね?
> > ちなみにサイズの固定はできないですよね〜?
> WS_THICKFRAME や WS_SIZEBOX も切ってしまえば良いかと。

教えていただいたとおりに
SetWindowLong(hWnd, GWL_STYLE, wStyle And (Not WS_MAXIMIZEBOX) And (Not WS_MINIMIZEBOX) And (Not WS_SYSMENU) And (Not WS_SIZEBOX) And (Not WS_THICKFRAME))
としてみたところ、サイズ固定にすることができました(^^)!
助かりました。本当にありがとうございます。
ダブルクリックでも最大化しませんでした。

今後もまた何かありましたらアドバイスお願いいたします。

[ツリー表示へ]
タイトルRe^6: Excelの最大化・最小化ボタン
記事No10011
投稿日: 2010/03/18(Thu) 10:17
投稿者花ちゃん
> > > Public Shared Function GetWindowLong(ByVal hWnd As Integer, ByVal nIndex As Integer) As Integer
> > こちらでは IntPtr にせず、Integer にしているのは何故でしょうか?
>
> 何も気にせずにGetWindowLongを.NET用に変換したものをネットで見つけてきて
> 使っていました。。ご指摘ありがとうございます。

No.10004 のレスで、 http://hanatyan.sakura.ne.jp/freesoft/win32api.htm を
紹介していたのに。
(見ても貰えませんでしたか?(T_T))

>xlApp.WindowState = xlNormal
この辺の定数はどのようにされているのでしょうか? 又、Excel の解放処理は?
プロセスが残っていなければいいのですが。

[ツリー表示へ]
タイトルRe^7: Excelの最大化・最小化ボタン
記事No10012
投稿日: 2010/03/18(Thu) 23:42
投稿者はる
> No.10004 のレスで、 http://hanatyan.sakura.ne.jp/freesoft/win32api.htm を
> 紹介していたのに。
> (見ても貰えませんでしたか?(T_T))

すみませんっ、ちゃんと見ていました!。
ただ他にもいろいろ検索していてごちゃごちゃになっていたのです。
でも言い訳ですね(_ _||)
せっかく丁寧に返信していただいたのに、いたらないばかりで申し訳ないです。m(_ _)m

> >xlApp.WindowState = xlNormal
> この辺の定数はどのようにされているのでしょうか? 又、Excel の解放処理は?
> プロセスが残っていなければいいのですが。

定数はExcelのオブジェクトブラウザで調べて、
Constで宣言しています。
プロセスの解放は花ちゃんさんのExcel関連の記事を参考にさせていただいて
ばっちりです。

「Excelのプロセスが正常に終了しない理由」を熟読しています。

[ツリー表示へ]