Password mask in InputBox massage

Sokkheng

Member
Local time
Today, 13:25
Joined
Jul 12, 2023
Messages
40
I have create code for user input password in input box for process to open form, but when show input box and we input the password it show the password (readable) not covert to password style (*******) how to covert InputBox in ms access to password mask when we typing.
this is my code:
Dim pw as string
pw=InputBox("inter password to open form")
If pw = "123456" then
Docmd.openForm "Account"
Else
MsgBox("Access denied")
End If
 
Take a look at the "similar threads" section below
 
I would use a popup form; but if you want an input box, you'll have to use an API for that.

Take a look here.
 
I would use a popup form; but if you want an input box, you'll have to use an API for that.

Take a look here.
Could you tell me more clear about to use API?
Thanks
 
Paste this code into a module:


Code:
Option Compare Database
Option Explicit

' Description:
'   This module is designed to provide an enhanced InputBox function that masks
'   password input with asterisks. It leverages Windows API calls to create a
'   hook procedure that intercepts the activation of an InputBox and modifies
'   it to behave like a password field.
'
'   The FormattedInputBox function can be used to prompt the user for a password
'   and returns the user's input as a masked string. The Test subroutine provides
'   an example of how to call this function.
'
'   The hard-coded class name "#32770" is used to identify dialog boxes in Windows,
'   including the InputBox, so that the password masking character can be set.
'
' Usage:
'   Call the FormattedInputBox function with the required prompt and optional title
'   to display a password InputBox. Use the returned string as needed in your code.

#If VBA7 Then
    ' Passes the hook information to the next handler in the chain
    Private Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As LongPtr, ByVal ncode As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
    ' Obtains a handle for the specified module
    Private Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
    ' Sets a Windows hook to monitor messages
    Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As LongPtr, ByVal hmod As LongPtr, ByVal dwThreadId As Long) As LongPtr
    ' Unhooks the Windows hook
    Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hhk As LongPtr) As Long
    ' Sends a message to a dialog item, controlling its behavior
    Private Declare PtrSafe Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    ' Retrieves the class name of a window
    Private Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    ' Gets the identifier for the current thread
    Private Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long
#Else
    ' Passes the hook information to the next handler in the chain
    Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
    ' Obtains a handle for the specified module
    Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
    ' Sets a Windows hook to monitor messages
    Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
    ' Unhooks the Windows hook
    Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hhk As Long) As Long
    ' Sends a message to a dialog item, controlling its behavior
    Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    ' Retrieves the class name of a window
    Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    ' Gets the identifier for the current thread
    Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
#End If

#If VBA7 Then
    ' The handle for managing the hook
    Private hHook As LongPtr
#Else
    ' The handle for managing the hook
    Private hHook As Long
#End If

' Code to set the password masking character
Private Const EM_SETPASSWORDCHAR As Long = &HCC

' Constants for handling Windows hooks and messages
Private Const WH_CBT As Long = 5
Private Const HCBT_ACTIVATE As Long = 5
Private Const HC_ACTION As Long = 0

' Purpose:  Intercepts the activation of an InputBox (or dialog box) and modifies it to mask password input with asterisks.
' Params:
'   - lngCode: Specifies the hook code
'   - wParam: Specifies the identifier of the window
'   - lParam: Additional information related to the message (depends on the hook code)
' Returns:  The value returned by the next hook in the chain if lngCode is less than HC_ACTION, otherwise returns no specific value.
#If VBA7 Then
Private Function NewProc(ByVal lngCode As Long, ByVal wParam As LongPtr, ByVal lParam As Long) As LongPtr
#Else
Private Function NewProc(ByVal lngCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#End If
    On Error GoTo Err_Handler

    Dim RetVal As Long          ' Holds the return value for GetClassName
    Dim lngBuffer As Long       ' Size of the buffer to hold the class name
    Dim strClassName As String  ' Buffer to receive the class name
    
    ' If the hook code is less than HC_ACTION, call the next hook
    If lngCode < HC_ACTION Then
        NewProc = CallNextHookEx(hHook, lngCode, wParam, lParam)
        Exit Function
    End If
    
    ' Prepare a buffer for the class name of the window
    strClassName = String$(256, " ")
    lngBuffer = 255
    
    ' Check if the hook call corresponds to the window activation
    If lngCode = HCBT_ACTIVATE Then
        ' Get the class name of the window being activated
        RetVal = GetClassName(wParam, strClassName, lngBuffer)
        
        ' If the class name corresponds to a dialog box (class name "#32770" is standard for dialog boxes in Windows),
        ' set the password masking character. This check helps to identify the InputBox window.
        If Left$(strClassName, RetVal) = "#32770" Then
            SendDlgItemMessage wParam, &H1324, EM_SETPASSWORDCHAR, Asc("*"), &H0
        End If
    End If
    
    ' Continue processing by calling the next hook in the chain
    CallNextHookEx hHook, lngCode, wParam, lParam

Exit_Err_Handler:
    Exit Function

Err_Handler:
    MsgBox "Error Number: " & Err.Number & vbCrLf & "Error Description: " & Err.Description & vbCrLf & "Procedure: NewProc", vbCritical + vbOKOnly, "NewProc - Error"
    Resume Exit_Err_Handler
End Function
 
' Purpose:  Display an InputBox with masked password input using a Windows hook to modify the InputBox behavior.
' Params:
'   - Prompt: The text string prompt that appears inside the InputBox.
'   - Title (Optional): The text string that appears in the title bar of the InputBox.
' Returns:  The user's input from the InputBox as a masked string.
Public Function FormattedInputBox(ByVal Prompt As String, Optional ByVal Title As String = vbNullString) As String
    On Error GoTo Err_Handler

    #If VBA7 Then
        Dim lngModHwnd As LongPtr   ' Handle to the module where the procedure is located
    #Else
        Dim lngModHwnd As Long      ' Handle to the module where the procedure is located
    #End If
    Dim lngThreadID As Long         ' Identifier of the current thread
    
    ' Get the current thread ID where the hook procedure will be installed
    lngThreadID = GetCurrentThreadId
    ' Get the module handle for the module containing the procedure to be hooked
    lngModHwnd = GetModuleHandle(vbNullString)
    
    ' Set the hook for the InputBox, pointing it to the NewProc function
    hHook = SetWindowsHookEx(WH_CBT, AddressOf NewProc, lngModHwnd, lngThreadID)

    ' Display the InputBox with the specified prompt and title, capturing the input with password masking
    FormattedInputBox = InputBox(Prompt, Title)
    ' Remove the hook after capturing the input, restoring normal InputBox behavior
    UnhookWindowsHookEx hHook

Exit_Err_Handler:
    Exit Function

Err_Handler:
    MsgBox "Error Number: " & Err.Number & vbCrLf & "Error Description: " & Err.Description & vbCrLf & "Procedure: FormattedInputBox", vbCritical + vbOKOnly, "FormattedInputBox - Error"
    Resume Exit_Err_Handler
End Function


And to test it you can try the following:

Code:
Public Sub Test()
    MsgBox "You entered: " & FormattedInputBox("Please enter a password", "Password Required"), vbInformation + vbOKOnly, "Masked Input"
End Sub
 
@Sokkheng I'm sure your code is just an example but that isn't a standard method. Usually you will have a table that defines users and their passwords. You will also have some table that defines authorization. Passwords should be hidden and they should never be used the way you are using them. Hard coding a password value is just not good technique.

There are several samples around that show you how to implement simple security. Here is a link to one of them. It is very simple and therefore limited but works for a lot of situations. The user is assigned four security levels, View, Add, Edit, Delete. Then the switchboard table which is used to choose the form to open also has the four security levels. The query that is bound to the switchboard form uses the View security value to restrict what options the user sees. If he can't even look at the data, the option to open the form is never shown to him. For the other security levels, each form needs code in four events Open, BeforeInsert, BeforeUpdate, OnDeleteConfirm that will compare the appropriate level for the person to what the form is restricted to. If the user's code is >= what the form is coded to allow, the user is allowed to complete the action. Otherwise, the data entry is undone using Me.Undo and the event is cancelled.

Although the switchboard can limit what the user sees, I still use code in the form's open event because I don't always want to hide options using the switchboard.

 
@Sokkheng I'm sure your code is just an example but that isn't a standard method. Usually you will have a table that defines users and their passwords. You will also have some table that defines authorization. Passwords should be hidden and they should never be used the way you are using them. Hard coding a password value is just not good technique.

There are several samples around that show you how to implement simple security. Here is a link to one of them. It is very simple and therefore limited but works for a lot of situations. The user is assigned four security levels, View, Add, Edit, Delete. Then the switchboard table which is used to choose the form to open also has the four security levels. The query that is bound to the switchboard form uses the View security value to restrict what options the user sees. If he can't even look at the data, the option to open the form is never shown to him. For the other security levels, each form needs code in four events Open, BeforeInsert, BeforeUpdate, OnDeleteConfirm that will compare the appropriate level for the person to what the form is restricted to. If the user's code is >= what the form is coded to allow, the user is allowed to complete the action. Otherwise, the data entry is undone using Me.Undo and the event is cancelled.

Although the switchboard can limit what the user sees, I still use code in the form's open event because I don't always want to hide options using the switchboard.

Thanks for your help.
 

Users who are viewing this thread

Back
Top Bottom