web-dev-qa-db-ja.com

進行状況バーのExcel vbaユーザーフォームの閉じる[X]ボタンを非表示

マクロがまだシートをインポートしているときにプログレスバーを表示するユーザーフォームを作成しました enter image description here

問題は、ユーザーが赤[X]ボタンを押すと、閉じて処理が中断されることです。

これを非表示にする方法はありますかDoomの赤いボタン実行中に潜在的なユーザーが混乱するボタンをクリックしないようにします。

編集:

私はこれを試しました

'Find the userform's Window
Private Declare Function FindWindow Lib "user32" _
        Alias "FindWindowA" ( _
        ByVal lpClassName As String, _
        ByVal lpWindowName As String) As Long

'Get the current window style
Private Declare Function GetWindowLong Lib "user32" _
        Alias "GetWindowLongA" ( _
        ByVal hWnd As Long, _
        ByVal nIndex As Long) As Long

'Set the new window style
Private Declare Function SetWindowLong Lib "user32" _
        Alias "SetWindowLongA" ( _
        ByVal hWnd As Long, _
        ByVal nIndex As Long, _
        ByVal dwNewLong As Long) As Long

Const GWL_STYLE = -16
Const WS_SYSMENU = &H80000

そして、私はこれをuserform_initializeで使用しました

   Dim hWnd As Long, lStyle As Long

   'Which type of userform
   If Val(Application.Version) >= 9 Then
      hWnd = FindWindow("ThunderDFrame", Me.Caption)
   Else
      hWnd = FindWindow("ThunderXFrame", Me.Caption)
   End If

   'Get the current window style and turn off the Close button
   lStyle = GetWindowLong(hWnd, GWL_STYLE)
   SetWindowLong hWnd, GWL_STYLE, (lStyle And Not WS_SYSMENU)

このエラーメッセージが表示されます enter image description here

このコードは here から取得されました。何が間違っているのかわからないので、すでにコメントを削除しました。これは私が見つけた最も単純なコードなので、ユーザーフォームに統合したいと思います。どんな助けも大歓迎です。

10
forums

以下は、このように呼び出すことができるルーチンです。

subRemoveCloseButton MyForm

またはフォーム内から:

subRemoveCloseButton Me 

必要なコードは次のとおりです。

Private Const mcGWL_STYLE = (-16)
Private Const mcWS_SYSMENU = &H80000

'Windows API calls to handle windows
#If VBA7 Then
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
#Else
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
#End If

#If VBA7 Then
    Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
#Else
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
#End If

#If VBA7 Then
    Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
#Else
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
#End If


Public Sub subRemoveCloseButton(frm As Object)
    Dim lngStyle As Long
    Dim lngHWnd As Long

    lngHWnd = FindWindow(vbNullString, frm.Caption)
    lngStyle = GetWindowLong(lngHWnd, mcGWL_STYLE)

    If lngStyle And mcWS_SYSMENU > 0 Then
        SetWindowLong lngHWnd, mcGWL_STYLE, (lngStyle And Not mcWS_SYSMENU)
    End If

End Sub
15
Peter Albert

次のスニペットから解決できます。

cmdCloseボタンを選択します。メニューバーで[View | Code]を選択します。カーソルが点滅している場所で、次のコードを入力します。

Private Sub cmdClose_Click()
  Unload Me
End Sub

メニューバーで[View | Object]を選択して、ユーザーフォームに戻ります。

ユーザーがEscキーを押してフォームを閉じることができるようにするには:

CmdCloseボタンを選択します。プロパティウィンドウで、CancelプロパティをTrueに変更します。

ユーザーがXボタンをクリックしてフォームを閉じるのを防ぐには

UserFormを開くと、右上にXがあります。 [フォームを閉じる]ボタンの使用に加えて、Xを使用してフォームを閉じることができます。それを防ぐには、次の手順を実行します。

UserFormの空の部分を右クリックし、View | Codeを選択します。右上の[プロシージャ]ドロップダウンから[QueryClose]を選択します。

カーソルが点滅している場所に、次のサンプルの強調表示されたコードを貼り付けます

Private Sub UserForm_QueryClose(Cancel As Integer, _
  CloseMode As Integer)
  If CloseMode = vbFormControlMenu Then
    Cancel = True
    MsgBox "Please use the Close Form button!"
  End If
End Sub

メニューバーで[View | Object]を選択して、ユーザーフォームに戻ります。これで、ユーザーフォームでXをクリックすると、メッセージが表示されます。

from http://www.contextures.com/xlUserForm01.html

10
JustinJDavies

これは、@ Peter Albertの上記の回答の改善です。

  • Windows API呼び出しがOffice x64で安全になりました
  • FindWindow呼び出しは、Excelユーザーフォームのみを検索するように改善されました。元の回答の関数は、すべてのウィンドウクラス(エクスプローラーウィンドウや他のプログラムのウィンドウなど)を検索します。そのため、他のプログラムまたはエクスプローラーウィンドウの[x]ボタンが、その名前がUserFormと同じ名前のときに削除された可能性があります。

Private Const mcGWL_STYLE = (-16)
Private Const mcWS_SYSMENU = &H80000

'Windows API calls to handle windows
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
    ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

#If Win64 Then
    Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" ( _
        ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
    Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" ( _
        ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
#Else
    Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongA" ( _
        ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
    Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongA" ( _
        ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
#End If

Public Sub RemoveCloseButton(objForm As Object)
    Dim lngStyle As LongPtr
    Dim lngHWnd As LongPtr

    Dim lpClassName As String
    lpClassName = vbNullString
    If Val(Application.Version) >= 9 Then
       lpClassName = "ThunderDFrame"
    Else
       lpClassName = "ThunderXFrame"
    End If

    lngHWnd = FindWindow(lpClassName, objForm.Caption)
    lngStyle = GetWindowLongPtr(lngHWnd, mcGWL_STYLE)

    If lngStyle And mcWS_SYSMENU > 0 Then
        SetWindowLongPtr lngHWnd, mcGWL_STYLE, (lngStyle And Not mcWS_SYSMENU)
    End If
End Sub

ThunderDFrame?
Excelのユーザーフォームは、実際にはWindowsクラスThunderDFrameです。これは、2002年以降のMicrosoft OfficeアプリケーションのすべてのUserFromsのクラスです。それ以前は、ThunderXFrameでした。

4
Pᴇʜ

Justin Daviesの貢献がかなり役立つことがわかりました。

MsgBox "Please use the Close Form button!"

UserformX.hide

ユーザーフォームはユーザーから隠されていますが、アンロードされるまでアクティブです。

3
Peter Balzer

これは古い質問ですが、OPが引用したユーザーフォームのタイプについては、閉じるボタンを削除、非表示、または無効にする必要はありません。もっと簡単な方法があります;)

ユーザーが操作する要素(ボタンなど)がなく、目的が終了すると自動的に閉じるユーザーフォームの場合、フォームを無効にするだけで十分です。

ユーザーフォームを無効にするには:ユーザーフォームのプロパティで、Enabledに対してFalseを設定します。ユーザーフォームは、コードが非表示にするよう指示するまで表示されます。ユーザーはフォームに対して何もできません(閉じることができず、移動できませんなど)

また、ユーザーフォームがまだ表示されている間にユーザーがメインウィンドウで他の操作を行えるようにするかどうかによって、ShowModalを設定するかどうかが決まります。

2
brit0n

フォームを閉じるかどうかをユーザーに尋ねます-そして、編集内容を失います(たとえば)。ジャスティンとピーターのアイデアに基づいています。

Private Sub UserForm_QueryClose(Cancel As Integer, _
                            CloseMode As Integer)
Dim ans
If CloseMode = vbFormControlMenu Then
    Cancel = True
    ans = Msgbox("Cancel edit?", vbQuestion + vbYesNo)
    If ans = vbYes Then
       Me.Hide
    End if
End If
End Sub

編集:実際には、OPがXオプションを削除したかったため、これは少し話題から外れていることに気付きました。

2
Richard Briggs

ボタンを無効にする便利な方法は、次を実行することです。

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = 0 Then Cancel = True
End Sub

これはボタンのget ridではありませんが、クリックしても何も実行されません。

2
Gravity Grave

次のリンクを確認してください。それは私のために働いた。 UserFormからTitleBarを削除します。

https://social.msdn.Microsoft.com/Forums/office/en-US/17452849-598c-410b-8675-b1e585d0e7e7/userform-without-titlebar-and-borders?forum=exceldev

1
Rahul Varadkar