I made a previous article on password protecting an application and also using Inputboxes to get the username and password. A comment was left on how to make the Inputbox show password characters instead of the actual password being inserted. Well, that is what this article is for, to show how to use .NET and set the Inputbox (Modal Window) to display the input in its textbox as password based characters like asterisks or another char instead of the actual password. Its also called masking the characters in the inputbox. This article will mask the inputbox using Asterisks. But you can set whatever you want the characters to be.
NOTE: While the code in this article is for Visual Basic.NET, VB 2008, and VB.NET 2010, the same principals apply to classic VB as well. You want to Subclass, checking for WM_Create messages. When a WM_Create message is activated, you want to use the Findwindow API to determine whether the newly created window matches the title of the Inputbox you want to show. If it is use GetWindow to get the handle to the Child window which is the edit/text box. Then use the SendMessage API to tell the first ChildWindow in the Inputbox to display all input characters as password characters like asterisks.
Update note 02/27/2011: Steve mentioned that the API call FindWindow may not format correctly when you use Auto in declaring it. So you may have to change Auto to “Ansi” instead. For example: Private Declare Ansi Function FindWindow…..
Instead of Auto or Unicode. The alias name in the api call ends with an ‘A’ which denotes Ansi. If it ended with ‘W’ then it would be Unicode based.
If you run into that problem, use this Declare instead of the one later in the article.
Private Declare Ansi Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Int32
AS outlined in a note above, the way I created a password only inputbox was to Subclass and monitor all the WM_Create messages being sent. When the application is notified that a new window was created, it will use the FindWindow API to check for the title of the newly created window. If the title of the window matches the title of the inputbox to be, it will return the handle to that window and call the GetWindow API function to get a handle to the first Child window, which with the Inputbox modal, is the Inputs Edit Box (Textbox) that you type the characters in. Once a handle to the Edit Box is taken, then a call to the SendMessage function to send a EM_SETPASSWORDCHAR message which will make the textbox display password characters which in this article tells the API to use Asterisks characters as the displayed password. You can make it display pretty much any character you want it to. That’s all I did!
'If you used the Declare Ansi Function FindWindow version above, then ignore this one. 'Will be used to get the window handles. Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Int32
Now for some more api calls and variables.
'Using it to get a handle to the child window of the inputbox. Private Declare Function GetWindow Lib "user32"? (ByVal hwnd As Int32, ByVal wCmd As Int32) As Int32 'It tells the editbox (textbox) to display the contents/input as password characters. Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Int32 'This will be the title of the Inputbox you will be throwing. 'This is important since this is the key factor that the example looks for to identify the Inputbox. Dim inputTitle As String = "Enter the Password!" 'Will hold the password returned by the inputbox message. Dim returnedPW As String 'Will be used to code the password characters to appear as Asterisk characters. 'You can actually have the password text display pretty much any character if you want too. 'Just change the value of the const to the keycode character you want to use. Const asteriskKeyCode As Int32 = 42 'Used by the SendMessage API to tell the inputbox editbox (textbox) to display the input as password characters. Public Const EM_SETPASSWORDCHAR As Int32 = &HCC 'The message for when a new window is created. Public Const WM_CREATE As Int32 = &H1 'Will hold the return value when calling the FindWindow function which will be the handle to the window. Dim windowHandle As Int32 'Used to have the API call to look for a child based window. Public Const GW_CHILD As Int32 = 5
Now that the APIs and Variables are setup, its time for the rest of the codes.
This is the code I put in a button control.
'This is a Button control I put some of the codes in… Private Sub btnDisplay_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisplay.Click ' 'Simply display the inputbox with the title specified in the inputTitle variable and get the value that was put in the edit box. ' 'IMPORTANT: The Inputbox is required to have the same title as the window title passed to the FindWindow function. You can try using the Classname if you want to I guess. ' 'Clear the previous correct password even if one wasn’t selected. lblPw.Text = "InputBox Password:" returnedPW = InputBox("Enter the Password in the box!", inputTitle, "password!", 0) If Not returnedPW = Nothing AndAlso returnedPW = "password!" Then lblPw.Text = "InputBox Password is: " & returnedPW Else lblPw.Text = "InputBox Password is: Wrong!" MessageBox.Show("Wrong Password!", " Try Again") End If End Sub
This will set the password if the subclass method said their is a inputbox matching the one we want.
Public Sub setPassword() 'The codes below will setup the Inputbox Textbox (Edit Window) to be a password edit box and use the asterisk character as the display character. Dim editWindow As Int32 'The Edit Window (Textbox) in the Inputbox is the first Child in the Inputbox Z Order. So just simply tell the API to get the handle to the first child window. editWindow = GetWindow(windowHandle, GW_CHILD) SendMessage(editWindow, EM_SETPASSWORDCHAR, asteriskKeyCode, 0) End Sub
Now for the subclass based procedure.
' 'This is used for the actual Subclassing to monitor for Created_Windows and will check to see if a Window matching the title of the inputbox we want. ' Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) 'Have the base class handle all messages. MyBase.WndProc(m) 'Check if a new window has been created. If m.Result.ToInt32 = WM_CREATE Then 'Check the new window to see if it has the charateristics that we are looking for. Namely that is has the Title that we want to find. windowHandle = FindWindow(vbNullString, inputTitle) 'Make sure that the WindowHandle is not 0 which should mean it have a handle to the Inputbox window that we are wanting. ElseIf windowHandle > 0 Then 'Call the code to set the textbox to a password textbox. setPassword() 'Reset the handle back to 0 since the window handle will be different each time you display Inputbox window. windowHandle = 0 End If End Sub
That’s all! As is usually the case, with my articles, there is a example available that show how to do this. Simply head over to my http://www.vbcodesource.com/ site and look under the Visual Basic.NET – Examples. Anyways, have fun!