- ベストアンサー
Excel VBA での画面最大化のロックについて
Excel2000 VBA で既存ツールの改造を行っています。 VBA内で画面を最大化、及びExcelのサイズ変更(最大化⇔標準化、最小化、消去)ボタンやメニューは消去しているのですが、最大化したExcel画面の上の枠(青色のタイトル欄)をダブルクリックすると、Excelの画面が標準化サイズに縮小してしまいます。 Excel画面の上の枠のダブルクリックでのサイズ変更をロックする方法をご存知の方、教えて頂けないでしょうか? 宜しくお願い致します。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
GetWindowLong、SetWindowLong は WindowsAPIで、Windows上の全ての ウィンドウに共通するアーキテクチャを 変更します。 例えば、どのウィンドウにもクラス名、 スタイル、拡張スタイル、プロシージャが あります。これらの情報を取得/変更 するのが上記APIです。Excelに限る話では ありません。 DispalyFullScreen=Trueはこのスタイルの CAPTION(BORDERとDLGFRAME)をOFFにする だけです。これですとSYSMENUが残るので、 ダブルクリックや「元に戻す」が有効なままです。 実際にフルスクリーンになった画面の上部で ダブルクリックすると元に戻ります。 なので、フルスクリーンにした直後に、スタイルの SYSMENUをOFFにすればよいでしょう。 スタイルには他に可視、許可、最大化ボタン、 最小化ボタン、枠など様々なフラグがあります。 例えば可視はWS_VISIBLE=&H10000000です。 これをOFFにすると見えなくなります。 スタイルは32ビット中の上位16ビットですが、 下位16ビットは拡張スタイルです。これも上記の APIで設定できます。索引は-20です。 どんなフラグがあるかはWS_xxx、WS_EX_xxを ネットで調べれば分かると思います。 最初に示したC言語サンプルでもプロシージャの 変更にSetWindowLongを使っています。 VBAでAPIを使えると、マルチスレッド以外の 大抵のことがVBAでできるようになります。 FTPでファイルを転送したり、マルチプロセスで 100業務を5個ずつ同時処理するなど自在です。
その他の回答 (4)
- nda23
- ベストアンサー率54% (777/1416)
昔使った手を思い出したので掲載します。 やはりAPIを使います。 Type RECT 左 As Long 上 As Long 右 As Long 下 As Long End Type Type WINDOWPLACEMENT バイト数 As Long フラグ As Long 表示形式 As Long 最小位置(1) As Long 最大位置(1) As Long RECT As 四辺 End Type Declare Function GetWindowPlacement Lib "USER32" _ (ByVal ウィンドウ As Long, 情報 As WINDOWPLACEMENT) As Long Declare Function SetWindowPlacement Lib "USER32" _ (ByVal ウィンドウ As Long, 情報 As WINDOWPLACEMENT) As Long Declare Function GetWindowRect Lib "USER32" _ (ByVal ウィンドウ As Long, 情報 As RECT) As Long Const WS_WS_THICKFRAME As Long = &H40000 '★画面を最大化した後に実行する Sub サンプル() Dim X As WINDOWPLACEMENT Dim S As Long 'ウィンドウの枠を変更不能にする S = GetWindowLong(Application.Hwnd, GWL_STYLE) S = S And (Not WS_WS_THICKFRAME) SetWindowLong Application.Hwnd, GWL_STYLE, S '最大化した時の位置、サイズ情報を記録する X.バイト数 = Len(X) GetWindowPlacement Application.Hwnd, X '最大化した時の四辺の位置を記録する GetWindowRect Application.Hwnd, X.サイズ '通常時の四辺の位置を設定する SetWindowPlacement Application.Hwnd, X End Sub 元のサイズに戻しても最大化の時のサイズに 近い大きさを保ちます。但し、画面は移動でき ます。
お礼
サンプルプログラムのご教示ありがとうございます。 到底、私には思いつかない技ですね。 プログラムを見て(実際はコメントを見ながらですが)、「なるほど」と思います。 VBAやAPIの知識を身に付け、少しでも「nda23さん」に近づけたらと思います。 本当にありがとうございました。
- nda23
- ベストアンサー率54% (777/1416)
Excelのウィンドウに対するイベントは 殆ど解放されていませんので、VBAで イベントを拾うことはできません。 究極的にはサブクラス化しかないの ですが、タイトルバーを消し、「元に 戻す」をできなくするには以下のように します。 Public Const GWL_STYLE As Long = -16 Public Const WS_CAPTION As Long = &HC00000 Public Const WS_SYSMENU As Long = &H80000 Public Declare Function GetWindowLong _ Lib "user32" Alias "GetWindowLongA" _ (ByVal ウィンドウ As Long, _ ByVal 索引 As Long) As Long Public Declare Function SetWindowLong _ Lib "user32" Alias "SetWindowLongA" _ (ByVal ウィンドウ As Long, _ ByVal 索引 As Long, _ ByVal 設定値 As Long) As Long Sub サンプル() Dim スタイル As Long スタイル = GetWindowLong(Application.hwnd, GWL_STYLE) スタイル = スタイル And (Not (WS_CAPTION Or WS_SYSMENU)) SetWindowLong Application.hwnd, GWL_STYLE, スタイル End Sub でも、画面がキレイじゃない気がするなぁ。
お礼
今回も親切なソース付きの回答、ありがとうございます。 タイトルバーを消すことは、「nak777rさん」に教えていただいた 「Application.DisplayFullScreen = True」で実現できたのですが、 「nda23さん」が回答下さっているSetWindowLong関数は、 「Application.DisplayFullScreen = True」とは結果が異なるのでしょうか? ちなみに現在は、VBA起動時(Workbook_Open関数)に「Application.DisplayFullScreen = True」を行い、 VBA終了時(Workbook_BeforeClose関数)に「Application.DisplayFullScreen = False」を行っています。 何度も質問ばかりして申し訳ありません。ご存知でしたら教えて下さい。 宜しくお願い致します。
- nak777r
- ベストアンサー率36% (49/136)
Application.DisplayFullScreen = True では駄目でしょうか?
お礼
回答、ありがとうございます。 「Excel画面の上の枠(青色のタイトル欄)をVBAで非表示にする。」 は「Application.DisplayFullScreen = True」で実現できました。
- nda23
- ベストアンサー率54% (777/1416)
C言語でDLLを作り、Excelのウィンドウ プロシージャをフックしてある種の メッセージを無効化します。 【Cプログラム】 static WNDPROC 旧プロシージャ = NULL; static LRESULT WINAPI フック( HWND ウィンドウ,UINT メッセージ, WPARAM Wパラメータ,LPARAM Lパラメータ) { //タイトルバーのダブルクリックを無効化 if ( メッセージ == WM_NCLBUTTONDBLCLK) return 0; //「元に戻す」を無効化 if ( メッセージ == WM_SYSCOMMAND ) { WPARAM x = (Wパラメータ & 0x0000FFFF); if ( x == SC_RESTORE ) return 0; } //上記以外は以前のプロシージャに制御を渡す return CallWindowProc(旧プロシージャ,ウィンドウ, メッセージ,Wパラメータ,Lパラメータ); } void WINAPI WindowSetup(HWND ウィンドウ) { if ( 旧プロシージャ ) { //設定済みなら解除する SetWindowLong(ウィンドウ,GWL_WNDPROC, (LONG)旧プロシージャ); 旧プロシージャ = NULL; } else { //未設定ならフックする 旧プロシージャ = (WNDPROC)GetWIndowLong( ウィンドウ,GWL_WNDPROC); SetWindowLong(ウィンドウ,GWL_WNDPROC,フック); } } 【VBA】 'DLLの定義 Declare Sub WindowSetup Lib "~" (ByVal ウィンドウ As Long) Sub サンプル() WindowSetup Application.hwnd 'フックする End Sub ★ このプロシージャはトグルになっており、 呼び出しの度に設定と解除を交互に繰り返す。 フックしたら終了前に必ず解除する。 フックした後でVBAがリセットされるかExcelが 終了すると異常が発生する。 ※VBAでフックプロシージャを作ると正しく動作 しない。 Cでビルドする時は定義ファイルでエントリ名を 指定しないと、VBAから呼び出せません。 Cコンパイラが無い場合は機械語をバイト配列に 組み込んで、そのエントリを呼び出すという、 ちょっと危ない方法もあります。 その時のコードは長いので、必要ならご相談 ください。
お礼
親切な回答、ありがとうございます。 DLLを作成し、メッセージの無効化を行うという高度な技ですね。 ということは、ダブルクリックでのサイズ変更(元に戻す)をVBA内でロックすることは不可能ということでしょうか。 今回は、可能な限りVBA内の改造で対応したいと考えています。 邪道かもしれませんが、以下のどれかの方法で最大化表示を実現したいと思っています。 1.ダブルクリックでのサイズ変更後、VBA内で「元に戻す」イベントを検出できれば、最大化処理を行う。 (ダブルクリック実行時、一瞬画面は小さくなるが、すぐに最大化表示に戻る。) 2.元に戻すサイズを最大化(最大化に近いサイズ)にVBA内で変更する。 3.Excel画面の上の枠(青色のタイトル欄)をVBAで非表示にする。 VBA初心者で、実現方法がわかっておりません。 ご存知でしたら教えて頂けないでしょうか。お手数掛けますが、宜しくお願い致します。 又、上記1~3以外にもVBA内の実現で、名案がありましたらご教示下さい。
お礼
何度も親切な回答ありがとうございます。 SetWindowLong関数を用いて試してみます。 画面の最大化以外にも「WS_xxx、WS_EX_xx」の種類を調べて、実際に動作させてみようと思います。