
PowerPoint VBAで複数のユーザーフォームからなるVBAマクロを作成しました。
フォーム内の「次へ」「前へ」ボタンでのみ、マクロの実行制御をしているので、途中で右上の×を押されると、想定外エラーが発生します。
そこで、一番下に貼りつけたようなコードを全てのフォームに挿入することで、右上の×が表示されないようにしました。
あくまでフォームにしかコードは埋め込んでいません。
(標準モジュール、クラスには入ってません)
ですが、極稀に、「フォームの右上×」ではなく、「PowerPointの右上×」が非表示になってしまう現象が発生します。
いろいろやるうちに再現はするのですが、厳密な再現手順がよくわかりません。
状況と下記ソースから、どこらへんに原因がありそうかアドバイス頂けないでしょうか?
全コードは出せない部分が多いのですが、アドバイスにあたり必要なコードがあれば、別途貼らせて頂きます。
Private Const GWL_STYLE = (-16)
Private Const WS_SYSMENU = &H80000
' ウィンドウに関する情報を返す
Private Declare Function GetWindowLong Lib "USER32.dll" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
' ウィンドウの属性を変更
Private Declare Function SetWindowLong Lib "USER32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
' Activeなウィンドウのハンドルを取得
Private Declare Function GetActiveWindow Lib "USER32.dll" () As Long
' メニューバーを再描画
Private Declare Function DrawMenuBar Lib "USER32.dll" (ByVal hWnd As Long) As Long
' フォームアクティブ時処理
Private Sub UserForm_Activate()
Dim hWnd As Long
Dim Wnd_STYLE As Long
hWnd = GetActiveWindow()
Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE)
Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
SetWindowLong hWnd, GWL_STYLE, Wnd_STYLE
DrawMenuBar hWnd
End Sub
No.1ベストアンサー
- 回答日時:
こんにちは。
今、見ただけで試験していませんが、どこかで拾ったコードでしょうか?
> hWnd = GetActiveWindow()
GetActiveWindow で、ハンドルを取るというのは目的が違うのではありませんか?
Office のバージョンによっても違いますが、現行では、UserForm のクラス名、"ThunderDFrame" だったはすですね。
だから、
Private Declare Function FindWindow Lib "USER32.dll" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
'-------------------------------------------
strClassName = "ThunderDFrame"
hWnd = FindWindow(strClassName, Me.Caption)
などとしますね。もしかしたら、UserForm 自身に、ハンドルを持っているバージョンもあったような気がしますが、そうしたら、直接使ってください。
'-------------------------------------------
それと、
>Private Const GWL_STYLE = (-16)
>Private Const WS_SYSMENU = &H80000
Long型と指定したほうがよいのでは?
最後に、通常、UserForm で終了ボタンは消さずに、QueryClose イベントで処理するはずです。
この回答への補足
回答ありがとうございます。
仰る通り、Webサイトを探して、参考にさせて頂いています。
正式には覚えていませんが、
http://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub0 …
このあたりだったと思います。
そのため、自分のコード用に移植まではできていますが、根本的な理解はあまい状態です。
Officeのバージョン情報が漏れていて申し訳ありません。
WinXP Pro、Office XP Proでやってます。
アドバイス頂いたコードの中までは理解できてませんので、まずそのまま組み込み挙動を見て、動作を確認してみたいと思います。
ちなみに×ボタンを非表示にした理由は、同僚に配布した際に「キャンセル」ボタンを押してくれずに「×」ボタンを押すので、キャンセルボタン使用を促すよりも消した方が手っ取り早いと思ったが故です。

No.3
- 回答日時:
こんにちは。
×ボタンを消すのではなくQueryCloseイベントで処理する方法です。
フォームを閉じるのはCommandButton1とします。
Private Sub CommandButton1_Click()
MsgBox "フォームを閉じます。"
Unload Me
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = 0 Then
MsgBox "×ボタンでは閉じません。"
Cancel = True
End If
End Sub
QueryCloseイベントのCloseModeで閉じられる原因(イベントの発生理由)が分かります。×ボタン以外にもいくつかあります。
詳しくはQueryCloseイベントのヘルプを参照してください。
この回答への補足
回答ありがとうございます。
バグの無いマクロを作るという観点では、×ボタン押下時の制御でも可ですが、
(システム要件としては、大丈夫ですが)
自分の考える配布の容易性のために、まずは×ボタン隠しを追求してみます。
No.2
- 回答日時:
こんにちは。
こういった処理の場合、私もGetActiveWindowではなくFindWindowを使用します。
確かにFormActiveの中なので略間違いなく取得できるかと思いますが安定性を考えると後者を選びます。
また、マクロ実行中に操作をされて困るようでしたらマクロ中フォーム内キーマウス無効化も視野に入れたほうが安定性は高まるかと考えます。
この回答への補足
No1の方のアドバイスとあわせて、おぼろげながら見えてきました。
GetActiveWindowだと、何らかの場合にフォームではなく、PowerPointウインドウをアクティブと認識する可能性があるんですね・・。
FindWindowというキーワードで調べてみたところ、具体的にフォーム名を第二引数に指定するので間違いがなさそうな気がしてきました。
第一引数部分が、XPの場合、orその他で同じで行けるのかどうかがわからないので、それをこれから調べてみることにします。
マクロが、
設定項目別に別フォームにしてあり、それらを「次へ」「前へ」ボタンで戻る際に頻繁に、開/閉をしているので、そこらへんが怖いですね・・・。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Access(アクセス) Vba Userformを前面に出すについて 3 2022/04/15 12:29
- Visual Basic(VBA) Vba LongPtrについて教えてください 2 2022/08/19 11:14
- Excel(エクセル) 【マクロ】スクショ印刷がうまく動かない件 5 2022/12/06 17:37
- Excel(エクセル) 【VBA】 Alt+PrintScreenにてアクティブウィンドウのスクショを貼付する方法 4 2022/12/08 20:53
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る バッチからEXEの結果を受け取りたいのですが、 下記のバッ 1 2023/07/04 15:13
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る EXEの実行内容の結果によって、戻り値を0か1かで返したい 1 2023/07/04 16:40
- Visual Basic(VBA) VBAで質問ですが、皆さんはどの様に導き出しているのでしょうか? 6 2022/05/03 21:53
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Excel(エクセル) B列に文字がはいったらA列に数字が入るマクロードを完成させたい 4 2023/04/21 01:58
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ユーザーフォームを表示中にシ...
-
ExcelVBAのユーザーフォームの...
-
VBAのテキストフォームの折り返...
-
クリックイベントなのに、2回ク...
-
エクセルのVBAでユーザーフォー...
-
Form_Load と Form_Activate の...
-
オブジェクト(コントロール)...
-
モーダルでフォームを開いた場合
-
【Excel VBA】ユーザフォームを...
-
VBAでユーザーフォームを再表示...
-
Microsoft Formsの「個人情報や...
-
テキストボックスの番号の取得
-
(Excel+VBA)ユーザーフォームの...
-
VB6の _ExtentX, _ExtentY
-
コントロールの存在確認
-
なぜエラーになるのでしょう?...
-
ユーザフォームの印刷
-
モーダルフォームとモードレス...
-
ユーザーフォーム
-
ACCESSのフォーム、開くんです...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ユーザーフォームを表示中にシ...
-
ExcelVBAのユーザーフォームの...
-
Form_Load と Form_Activate の...
-
VBAでユーザーフォームを再表示...
-
Microsoft Formsの「個人情報や...
-
クリックイベントなのに、2回ク...
-
ユーザーフォームのテキストボ...
-
ユーザーフォーム上に現在日時...
-
ACCESSのフォーム、開くんです...
-
エクセルのチェックボックスの...
-
エクセルVBAのフォームを最...
-
VB.NETでフォームロード中のエ...
-
EXCEL VBA ユーザーフォームの...
-
VBA(エクセル)のユーザー...
-
【Excel VBA】ユーザフォームを...
-
Hideについて(.NET)
-
(Excel+VBA)ユーザーフォームの...
-
モーダルフォームとモードレス...
-
VBA コンボボックスとテキスト...
-
アクセス2013 フォームが...
おすすめ情報