StringGadget for passwords - toggle '*'?
StringGadget for passwords - toggle '*'?
I need to be able to toggle a string gadget's "*" -- can this be done?
Re: StringGadget for passwords - toggle '*'?
yes, of course:jassing wrote:can this be done?
Code: Select all
Enumeration
#myWindow
EndEnumeration
Enumeration
#myPasswortField
#chkToggle
EndEnumeration
If OpenWindow(#myWindow, #PB_Ignore, #PB_Ignore, 300, 100, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
TextGadget(#PB_Any, 5, 5, 70, 30, "Password:")
StringGadget(#myPasswortField, 80, 5, 200, 30, "mySecretPassword", #PB_String_Password)
CheckBoxGadget(#chkToggle, 5, 40, 200, 30, "Show Password")
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #chkToggle
If GetGadgetState(#chkToggle)
StringGadget(#myPasswortField, 80, 5, 200, 30, GetGadgetText(#myPasswortField))
Else
StringGadget(#myPasswortField, 80, 5, 200, 30, GetGadgetText(#myPasswortField), #PB_String_Password)
EndIf
EndSelect
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
EndIf
Hygge
Re: StringGadget for passwords - toggle '*'?
It is not necessary to always recreate the complete StringGadget as in Kiffi's example
although Kiffi's example doesn't use API calls and therefore is usable cross-platform.
My example uses Windows API calls and therefore is only usable in Windows:
If you have XP-Style activated you also have to activate "Create unicode executable"
in "Compiler Options" to get back your initial password character:
although Kiffi's example doesn't use API calls and therefore is usable cross-platform.
My example uses Windows API calls and therefore is only usable in Windows:
Code: Select all
OpenWindow(0, 20, 20, 150, 70, "Toggle password")
StringGadget(0, 30, 10, 80, 20, "Test", #PB_String_Password)
ButtonGadget(1, 10, 40, 130, 20, "Toggle password mode")
PasswordChar = SendMessage_(GadgetID(0), #EM_GETPASSWORDCHAR, 0, 0)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
If EventGadget() = 1
If GetWindowLong_(GadgetID(0), #GWL_STYLE) & #ES_PASSWORD
SendMessage_(GadgetID(0), #EM_SETPASSWORDCHAR, 0, 0)
Else
SendMessage_(GadgetID(0), #EM_SETPASSWORDCHAR, PasswordChar, 0)
EndIf
InvalidateRect_(GadgetID(0), 0, 1)
EndIf
EndSelect
ForEver
in "Compiler Options" to get back your initial password character:
MSDN wrote:Windows XP: If an edit control is from user32.dll, an asterisk is the default character for the ES_PASSWORD style. However, if an edit control is from comctl32.dll version 6, a black circle is the default character for the ES_PASSWORD style. Note that comctl32.dll version 6 is not redistributable but is included with Windows XP or later. To use comctl32.dll version 6, specify it in a manifest.
Re: StringGadget for passwords - toggle '*'?
yes, that was my intention.Shardik wrote:although Kiffi's example doesn't use API calls and therefore is usable cross-platform.
Greetings ... Kiffi (developing currently under Ubuntu)
Hygge
Re: StringGadget for passwords - toggle '*'?
In Linux using API is even shorter and easier than in Windows:Kiffi wrote:Greetings ... Kiffi (developing currently under Ubuntu)

Code: Select all
OpenWindow(0, 20, 20, 200, 70, "Toggle password")
StringGadget(0, 50, 10, 100, 20, "Test", #PB_String_Password)
ButtonGadget(1, 10, 40, 180, 23, "Toggle password mode")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
If EventGadget() = 1
gtk_entry_set_visibility_(GadgetID(0), gtk_entry_get_visibility_(GadgetID(0)) ! 1)
EndIf
EndSelect
ForEver
of Gadgets is only possible with static Gadget-IDs. So reusing dynamic Gadget-IDs created
with #PB_Any is not possible (see explanation by Trond):
http://www.purebasic.fr/english/viewtop ... 03&start=3
Re: StringGadget for passwords - toggle '*'?
Thank you -- Yes, I need to retain cross platform.. so I need to avoid api's.
thank you both for your examples.
thank you both for your examples.
Re: StringGadget for passwords - toggle '*'?
You only need to avoid API calls if you don't have API solutions for all platformsjassing wrote:Yes, I need to retain cross platform.. so I need to avoid api's.
at hand.

two example codes into one:
Code: Select all
EnableExplicit
Procedure TogglePasswordVisibility()
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
gtk_entry_set_visibility_(GadgetID(0), gtk_entry_get_visibility_(GadgetID(0)) ! 1)
CompilerCase #PB_OS_Windows
Static PasswordChar
Static PasswordCharIsKnown
If PasswordCharIsKnown = #False
PasswordChar = SendMessage_(GadgetID(0), #EM_GETPASSWORDCHAR, 0, 0)
PasswordCharIsKnown = #True
EndIf
If GetWindowLong_(GadgetID(0), #GWL_STYLE) & #ES_PASSWORD
SendMessage_(GadgetID(0), #EM_SETPASSWORDCHAR, 0, 0)
Else
SendMessage_(GadgetID(0), #EM_SETPASSWORDCHAR, PasswordChar, 0)
EndIf
InvalidateRect_(GadgetID(0), 0, 1)
CompilerEndSelect
EndProcedure
OpenWindow(0, 20, 20, 200, 70, "Toggle password mode")
StringGadget(0, 50, 10, 100, 20, "Test", #PB_String_Password)
ButtonGadget(1, 10, 40, 180, 23, "Toggle password mode")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
If EventGadget() = 1
TogglePasswordVisibility()
EndIf
EndSelect
ForEver
Re: StringGadget for passwords - toggle '*'?
Kiffi's original snippet shortened slightly with a bitshift eliminating the 'If' statement. ( no real reason why I did this. Just a little bored & playing silly buggers atm...)

Code: Select all
Enumeration
#myWindow
EndEnumeration
Enumeration
#myPasswortField
#chkToggle
EndEnumeration
If OpenWindow(#myWindow, #PB_Ignore, #PB_Ignore, 300, 100, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
TextGadget(#PB_Any, 5, 5, 70, 30, "Password:")
StringGadget(#myPasswortField, 80, 5, 200, 30, "mySecretPassword", #PB_String_Password)
CheckBoxGadget(#chkToggle, 5, 40, 200, 30, "Show Password")
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #chkToggle
StringGadget(#myPasswortField, 80, 5, 200, 30, GetGadgetText(#myPasswortField),#PB_String_Password-GetGadgetState(#chkToggle)<<5)
EndSelect
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
EndIf
Re: StringGadget for passwords - toggle '*'?
Thanks for this interesting thread 
@ Baldrick
to maintain crossplatform capability << 5 needs to be exchanged with | #PB_String_BorderLess

@ Baldrick
to maintain crossplatform capability << 5 needs to be exchanged with | #PB_String_BorderLess

Two growing code-collections: WinApi-Lib by RSBasic ~ LinuxAPI-Lib by Omi
Missing a download-file on the forums? ~ check out this backup page.
Missing a download-file on the forums? ~ check out this backup page.
Re: StringGadget for passwords - toggle '*'?
Not sure what you mean here Vera. All I am doing really is using the '0' or '1' value from a checkbox gadget & bitshifting that value to be used in the stringgadget flags. It will work with multiple flags as per this snippet below which is doing the same thing using multiple flags on the stringgadget() or whatever other gadget that supports flags, which allow modification on the fly.Vera wrote:Thanks for this interesting thread
@ Baldrick
to maintain crossplatform capability << 5 needs to be exchanged with | #PB_String_BorderLess
Am I missing something?
Code: Select all
Enumeration
#myWindow
EndEnumeration
Enumeration
#myPasswortField
#chkToggle
#chkReadOnly
#chkBorder
EndEnumeration
PassShift=CountString(Bin(#PB_String_Password),"0") ; set variables for number of places to shift checkbox status values
ReadOnlyShift=CountString(Bin(#PB_String_ReadOnly),"0") ; called at start of app is sufficient
BorderShift=CountString(Bin(#PB_String_BorderLess),"0") ; no need to call continually
If OpenWindow(#myWindow, #PB_Ignore, #PB_Ignore, 300, 100, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
TextGadget(#PB_Any, 5, 5, 70, 30, "Password:")
StringGadget(#myPasswortField, 80, 5, 200, 30, "mySecretPassword", #PB_String_Password); #PB_String_Password see note below
CheckBoxGadget(#chkToggle, 5, 40, 100, 30, "Show Password")
CheckBoxGadget(#chkReadOnly, 110, 40, 100, 30, "Read Only")
CheckBoxGadget(#chkBorder, 5, 70, 100, 30, "Hide Border")
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #chkToggle,#chkReadOnly,#chkBorder ; the checkboxes we need to watch & recalculate when any of them change state
Password=#PB_String_Password-GetGadgetState(#chkToggle)<<PassShift
;password is calculated differently because it is set to hide as default with this window.
;If it was worded as 'Hide Password'& password flag not set, then you would not do the subtraction calculation
;i.e. GetGadgetState(#chkToggle)<<PassShift
ReadOnly=GetGadgetState(#chkReadOnly)<<ReadOnlyShift
Border=GetGadgetState(#chkBorder)<<BorderShift
FlagOptions=Password|ReadOnly|Border ; Bitwise Or your new values together
StringGadget(#myPasswortField, 80, 5, 200, 30, GetGadgetText(#myPasswortField),FlagOptions); set gadget with new flag options
EndSelect
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
EndIf
Re: StringGadget for passwords - toggle '*'?
I meant, that the values of the #PB_constants vary on the platforms, so '5' doesn't work on Linux. (It toggles the border but not the password)Baldrick wrote:Not sure what you mean here Vera.
If you'd insert the following you can make out the differences:
Debug PassShift ; win=5 - linux=0
Debug ReadOnlyShift ; win=11 - linux=1
Debug BorderShift ; win=17 - linux=5
toggle checkbox on/off
Debug ReadOnly ; win=2048/0 - linux=2/0
Debug Border ; win=131072/0 - linux=32/0
Debug FlagOptions ; win=0/32 - linux=0/1 (only toggle password)
and thanks for your commented enhanced code. It works straight and again gives me some more insights

greeting ~ Vera
Two growing code-collections: WinApi-Lib by RSBasic ~ LinuxAPI-Lib by Omi
Missing a download-file on the forums? ~ check out this backup page.
Missing a download-file on the forums? ~ check out this backup page.
Re: StringGadget for passwords - toggle '*'?
Another of those "Ahaaa" moments for me Vera.Vera wrote:I meant, that the values of the #PB_constants vary on the platforms, so '5' doesn't work on Linux. (It toggles the border but not the password)Baldrick wrote:Not sure what you mean here Vera.
If you'd insert the following you can make out the differences:
Thanks for that information

Nb: I must fix my Linux machine 1 of these days so I can test these things......


-
- Addict
- Posts: 4777
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: StringGadget for passwords - toggle '*'?
Shardik, many thanks for that code! That's what I need at the moment.Shardik wrote:You only need to avoid API calls if you don't have API solutions for all platforms
at hand.If you only need to support Windows and Linux, you can combine my
two example codes into one:

I've got two suggestions for improvement.
GetWindowLong_() should be replaced with GetWindowLongPtr_().Shardik wrote:Code: Select all
CompilerCase #PB_OS_Windows [...] If GetWindowLong_(GadgetID(0), #GWL_STYLE) & #ES_PASSWORD [...]
Another problem is, that your fine TogglePasswordVisibility() procedure currently only works in the special case for a string gadget with number 0. For general usage, the procedure should take a gadget number as parameter (say 'gad'), and then inside the procedure replace GadgetID(0) with GadgetID(gad).[u]PureBasic Team Blog[/u] wrote:Do NOT use Get/SetWindowLong_() for subclassing anymore. These remain 32bit even on x64. Use Get/SetWindowLongPtr_() instead, which works correctly everywhere. There is really no need to use SetWindowLong_() over SetWindowLongPtr_() actually, so best do a search and replace and replace all of them right away.
Thanks again!
Re: StringGadget for passwords - toggle '*'?
Cross Platform
Code: Select all
If OpenWindow(0, 0,0, 300, 100, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
StringGadget(0, 10, 10, 200, 20, "mySecretPassword",#PB_String_Password)
toggle = StringGadget(#PB_Any, 10, 10, 200, 20, "mySecretPassword")
ButtonGadget(3,10,65,60,25,"Toggle")
HideGadget(toggle,1)
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case 0
SetGadgetText(toggle,GetGadgetText(0))
Case toggle
SetGadgetText(0,GetGadgetText(toggle))
Case 3
run ! 1
If Run = 1
HideGadget(0,1)
HideGadget(toggle,0)
Else
HideGadget(toggle,1)
HideGadget(0,0)
EndIf
EndSelect
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
EndIf
Egypt my love
Re: StringGadget for passwords - toggle '*'?
I am glad that my code example was usefull for you.Little John wrote:Shardik, many thanks for that code! That's what I need at the moment.
Thank you for reminding me about still having used GetWindowLong() in my code example from December 2010. But in June 2011 I already proposed to use GetWindowLongPtr() by myself in this posting citing MSDN...Little John wrote:GetWindowLong_() should be replaced with GetWindowLongPtr_().Shardik wrote:Code: Select all
CompilerCase #PB_OS_Windows [...] If GetWindowLong_(GadgetID(0), #GWL_STYLE) & #ES_PASSWORD [...]
[u]PureBasic Team Blog[/u] wrote:Do NOT use Get/SetWindowLong_() for subclassing anymore. These remain 32bit even on x64. Use Get/SetWindowLongPtr_() instead, which works correctly everywhere. There is really no need to use SetWindowLong_() over SetWindowLongPtr_() actually, so best do a search and replace and replace all of them right away.

Again you're right. I therefore adapted my code example and even added the MacOS part (which was the most difficult one because I had to mess around with PureBasic and Cocoa framework internals). Below is my now true cross-platform example tested successfully on the following operating systems:Little John wrote:Another problem is, that your fine TogglePasswordVisibility() procedure currently only works in the special case for a string gadget with number 0. For general usage, the procedure should take a gadget number as parameter (say 'gad'), and then inside the procedure replace GadgetID(0) with GadgetID(gad).
- Linux Mint 17.3 'Sylvia' x64 with Cinnamon using PB 5.46 x64 in ASCII- and Unicode mode with Gtk2 and Gtk3
- MacOS 10.6.8 'Snow Leopard' using PB 5.46 x86 in ASCII- and Unicode mode
- MacOS 10.13.6 'High Sierra' using PB 5.46 x64 in ASCII- and Unicode mode
- Windows 7 SP1 x64 using PB 5.46 x86 in Unicode mode (ASCII mode doesn't work!)
- Windows 10 x64 1809 using PB 5.46 x86 and x64 in Unicode mode (ASCII mode doesn't work!)
- Xubuntu 18.04 x86 using PB 5.70 x86 with Gtk2, Gtk3 and Qt
Warning: although you have to call TogglePasswordVisibility() now with the number of your StringGadget, the procedure currently doesn't allow to work with more than one encrypted StringGadget cross-platform. On MacOS it would be necessary to define an array holding the different cells for each StringGadget and on Windows the Static variables would have to be taken care of. For the sake of keeping the example as easy and short as possible, I have not implemented this feature.
Update: I have added wombat's code to also support the new Qt subsystem in Linux.
Code: Select all
EnableExplicit
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
Define SecuredPasswordCell.I
Define VisiblePasswordCell.I
CompilerEndIf
Procedure TogglePasswordVisibility(StringGadgetID.I)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
CompilerIf Subsystem("qt")
If Val(QtScript("gadget(" + Str(StringGadgetID) + ").echoMode")) = 2
QtScript("gadget(" + Str(StringGadgetID) + ").echoMode = 0")
ElseIf Val(QtScript("gadget(" + Str(StringGadgetID) + ").echoMode")) = 0
QtScript("gadget(" + Str(StringGadgetID) + ").echoMode = 2")
EndIf
CompilerElse
gtk_entry_set_visibility_(GadgetID(StringGadgetID),
gtk_entry_get_visibility_(GadgetID(StringGadgetID)) ! 1)
CompilerEndIf
CompilerCase #PB_OS_MacOS
Shared SecuredPasswordCell.I
Shared VisiblePasswordCell.I
Protected Cell.I
Protected Password.S
Password = GetGadgetText(StringGadgetID)
If PeekS(CocoaMessage(0, CocoaMessage(0, CocoaMessage(0,
GadgetID(StringGadgetID), "cell"), "className"), "UTF8String"),
-1, #PB_UTF8) = "NSSecureTextFieldCell"
If VisiblePasswordCell = 0
SecuredPasswordCell = CocoaMessage(0, GadgetID(StringGadgetID),
"cell")
CocoaMessage(0, SecuredPasswordCell, "retain")
VisiblePasswordCell = CocoaMessage(0, CocoaMessage(0,
CocoaMessage(0, 0, "NSTextField alloc"), "initWithFrame:", 0),
"cell")
CocoaMessage(0, VisiblePasswordCell, "retain")
EndIf
CocoaMessage(0, GadgetID(StringGadgetID),
"setCell:", VisiblePasswordCell)
CocoaMessage(0, VisiblePasswordCell, "setStringValue:$", @Password)
CocoaMessage(0, GadgetID(StringGadgetID), "setNeedsDisplay:", #YES)
Else
If SecuredPasswordCell
CocoaMessage(0, GadgetID(StringGadgetID),
"setCell:", SecuredPasswordCell)
CocoaMessage(0, SecuredPasswordCell, "setStringValue:$", @Password)
CocoaMessage(0, GadgetID(StringGadgetID), "setNeedsDisplay:", #YES)
EndIf
EndIf
CompilerCase #PB_OS_Windows
Static PasswordChar
Static PasswordCharIsKnown
If PasswordCharIsKnown = #False
PasswordChar = SendMessage_(GadgetID(StringGadgetID),
#EM_GETPASSWORDCHAR, 0, 0)
PasswordCharIsKnown = #True
EndIf
If GetWindowLongPtr_(GadgetID(StringGadgetID),
#GWL_STYLE) & #ES_PASSWORD
SendMessage_(GadgetID(StringGadgetID), #EM_SETPASSWORDCHAR, 0, 0)
Else
SendMessage_(GadgetID(StringGadgetID), #EM_SETPASSWORDCHAR,
PasswordChar, 0)
EndIf
InvalidateRect_(GadgetID(StringGadgetID), 0, 1)
CompilerEndSelect
EndProcedure
OpenWindow(0, 270, 100, 250, 90, "Toggle password visibility")
StringGadget(0, 40, 20, 180, 20, "Test", #PB_String_Password)
ButtonGadget(1, 40, 55, 180, 25, "Toggle password visibility")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
CocoaMessage(0, VisiblePasswordCell, "release")
CompilerEndIf
Break
Case #PB_Event_Gadget
If EventGadget() = 1
; ----- Only necessary for MacOS to work correctly after adding or
; deleting characters
SetActiveGadget(-1)
TogglePasswordVisibility(0)
EndIf
EndSelect
ForEver
Last edited by Shardik on Mon Mar 25, 2019 2:21 pm, edited 4 times in total.