Page 1 of 1

Tip: InputBox

Posted: Fri Oct 25, 2002 10:08 pm
by BackupUser
Code updated For 5.20+

Restored from previous forum. Originally posted by PB.

Here's my own version of an input requester, which is superior to the
built-in InputRequester() command in these ways:

(1) It's "modal" (it locks the calling window until done).
(2) The prompt area is bigger and can have multi-line text.
(3) It has a Cancel button in addition to an OK button.
(4) It has a standard Windows look-and-feel about it.
(5) It plays the "question" audio prompt sound.

It works with or without a calling window, and here's how you call it:

a$=InputBox(title$,prompt$,default$)

Naturally prompt$ can include Chr(13) for multi-line text, and default$
can be empty (null) if you don't want a default entry placed in it.
I called it InputBox() so as not to clash with InputRequester(), and
because it emulates the Visual Basic InputBox() command.

Code edited out, see new v4.00 version below.

Posted: Sat Oct 26, 2002 6:50 am
by BackupUser
Restored from previous forum. Originally posted by TronDoc.

I will try it at my first opportunity.
It sounds very well thought out.
Joe

elecTRONics DOCtor
{registeredPB}P150 32Mb w98/DOS/Linux NO DirX NO IE :wink:

Posted: Sat Oct 26, 2002 10:30 am
by BackupUser
Restored from previous forum. Originally posted by redacid.

Very nice! Just what I´ve been searching for (because I was too lazy to do it myself)...

regards,
Redacid
---
Viva Los Tioz!
registered user of PB3.20 on WinXP

Posted: Tue Oct 29, 2002 10:29 am
by BackupUser
Restored from previous forum. Originally posted by waffle.

i'm always amazed at how much work is invovled to do something so "simple" in windows :)

Posted: Tue Oct 29, 2002 10:50 am
by BackupUser
Restored from previous forum. Originally posted by Fangbeast.

I'm always amazed at PB's imagination. He not only comes up with some great solutions, he also explains them.

Good on ya mate !! :)

Fangles woz ear orright den?

Posted: Tue Oct 29, 2002 11:10 am
by BackupUser
Restored from previous forum. Originally posted by TheBeck.

Thanks PB, I've added this to my IncludeFile stash. :)

Posted: Tue Oct 29, 2002 11:31 pm
by BackupUser
Restored from previous forum. Originally posted by PB.

Thanks for the kind words, everyone. :)


PB - Registered PureBasic Coder

Posted: Wed Mar 01, 2006 8:26 pm
by PB
Code updated For 5.20+

And here's an enhanced update that works with PureBasic v4.30, which now
supports a password flag and also returns Chr(1) if the InputBox is cancelled
by the user (which is great to know because just returning null won't tell you
if the requester was cancelled or an empty string entered). Enjoy! :)

Code: Select all

Procedure.s InputBox(title$,prompt$,def$,password)
  box=OpenWindow(999,0,0,500,145,title$,#PB_Window_ScreenCentered)
  If box<>0
    TextGadget(996,6,8,487,70,prompt$)
    If password=0 : flags=#ES_MULTILINE|#ES_AUTOVSCROLL : Else : flags=#PB_String_Password|#ES_AUTOVSCROLL : EndIf
    StringGadget(997,6,85,487,20,def$,flags) : ButtonGadget(998,365,114,60,23,"OK") : ButtonGadget(999,433,114,60,23,"Cancel")
    SendMessage_(GadgetID(997),#EM_SETSEL,0,Len(def$)) : GetAsyncKeyState_(#VK_RETURN) : GetAsyncKeyState_(#VK_ESCAPE)
    StickyWindow(999,#True) : SetForegroundWindow_(WindowID(999)) : SetActiveGadget(997) : MessageBeep_(#MB_ICONQUESTION)
    Repeat
      ev=WaitWindowEvent(1) : id=EventGadget() : ret=GetAsyncKeyState_(#VK_RETURN) : esc=GetAsyncKeyState_(#VK_ESCAPE)
      a=GetForegroundWindow_()
      If a<>box
        thread1=GetWindowThreadProcessId_(@a,0) : thread2=GetWindowThreadProcessId_(@box,0)
        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
        SetForegroundWindow_(box) : Sleep_(1)
        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf
        SetActiveGadget(997) : MessageBeep_(#MB_ICONQUESTION)
      EndIf
    Until (ev=#PB_Event_Gadget And (id=998 Or id=999)) Or ret<>0 Or esc<>0 Or ev=#PB_Event_CloseWindow
    If id=998 Or ret<>0 : text$=GetGadgetText(997) : Else : text$=Chr(1) : EndIf
    CloseWindow(999)
  EndIf
  ProcedureReturn text$
EndProcedure

a$=InputBox("Test","Enter something:","default",0) ; Use 1 at end for passwords.
If a$=Chr(1) : Debug "InputBox cancelled" : Else : Debug a$ : EndIf

Posted: Thu Mar 02, 2006 4:26 am
by NoahPhense
nice..

Posted: Thu Mar 02, 2006 8:40 am
by Rescator
Same as the cool code above,
only the return value/text is slightly differently handled.
And if your lazy this means you do not really have to check at all if the user clicked cancel, the code will handle that itself :)

Code: Select all

Procedure.s InputBox(title$,prompt$,def$,password)
  box=OpenWindow(999,0,0,360,145,#PB_Window_ScreenCentered,title$)
  If box<>0 And CreateGadgetList(WindowID(999))<>0
    TextGadget(996,6,8,347,70,prompt$)
    If password=0 : flags=#ES_MULTILINE|#ES_AUTOVSCROLL : Else : flags=#PB_String_Password|#ES_AUTOVSCROLL : EndIf
    StringGadget(997,6,85,347,20,def$,flags) : ButtonGadget(998,225,114,60,23,"OK") : ButtonGadget(999,293,114,60,23,"Cancel")
    SendMessage_(GadgetID(997),#EM_SETSEL,0,Len(def$)) : GetAsyncKeyState_(#VK_RETURN) : GetAsyncKeyState_(#VK_ESCAPE)
    StickyWindow(999,#True) : SetForegroundWindow_(WindowID(999)) : SetActiveGadget(997) : MessageBeep_(#MB_ICONQUESTION)
    Repeat
      ev=WaitWindowEvent(1) : id=EventGadget() : ret=GetAsyncKeyState_(#VK_RETURN) : esc=GetAsyncKeyState_(#VK_ESCAPE)
      a=GetForegroundWindow_()
      If a<>box
        thread1=GetWindowThreadProcessId_(@a,0) : thread2=GetWindowThreadProcessId_(@box,0)
        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
        SetForegroundWindow_(box) : Sleep_(1)
        If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf
        SetActiveGadget(997) : MessageBeep_(#MB_ICONQUESTION)
      EndIf
    Until (ev=#PB_Event_Gadget And (id=998 Or id=999)) Or ret<>0 Or esc<>0 Or ev=#PB_Event_CloseWindow
    If id=998 Or ret<>0 : text$=GetGadgetText(997) : Else : text$=def$ : EndIf
    CloseWindow(999)
  EndIf
  ProcedureReturn text$
EndProcedure


;Will automaticaly return the default value if the user hit cancel
a$=InputBox("Test","Enter something:","default",0)
Debug a$

;and if you wish to "know" if the user actualy pressed cancel

If a$="default" : Debug "InputBox cancelled" : Else : Debug a$ : EndIf

Posted: Thu Mar 02, 2006 8:56 am
by bingo
simple ... but effective :lol:

Code: Select all

Procedure.s Uni2Ansi(*Unicode.l) 
size.l = WideCharToMultiByte_(#CP_ACP, 0, *Unicode, -1, #Null, #Null, #Null, #Null) 
ansi.s=Space(size) 
WideCharToMultiByte_(#CP_ACP, 0, *Unicode, -1, @ansi, size, #Null, #Null) 
ProcedureReturn ansi  
EndProcedure

Procedure.l Ansi2Uni(ansi.s) ;short way to unicode
SHStrDup_(@ansi,@memtarget)
ProcedureReturn memtarget
EndProcedure

Structure VARIANT 
  vt.w 
  wReserved1.w 
  wReserved2.w 
  wReserved3.w 
  StructureUnion 
     cVal.b                                        
     iVal.w                                       
     lVal.l                                          
     bstrVal.l                                  
     pdispVal.l                           
  EndStructureUnion 
EndStructure 

Global VarResult.VARIANT

Procedure showhtmlwin(source.s)
*pMoniker.IMoniker
res = CreateURLMoniker_(0, Ansi2Uni(source),@*pMoniker)
If res = 0
OpenLibrary(1,"mshtml.dll")
CallFunction (1, "ShowHTMLDialog",FindWindow_("Progman", "Program Manager"), *pMoniker,0 ,ansi2uni("help:no;status:0;unadorned:1") ,@VarResult)
*pMoniker\release()
CloseLibrary(1)
EndIf
EndProcedure

showhtmlwin("res://" + GetFilePart(ProgramFilename()) + "/input.htm")

MessageRequester("input return ...",uni2ansi(VarResult\pdispVal),#PB_MessageRequester_Ok)

End
input.htm for pb-resources

Code: Select all

<HTML id=dlgAbout  STYLE="width: 200; height: 100;">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<HEAD>
</HEAD>
<SCRIPT LANGUAGE="JavaScript">
function testResults (form) {
window.returnValue = form.inputbox.value;
window.close()
}
</SCRIPT>
<BODY onload="self.focus(); document.inputform.inputbox.focus();">
<FORM NAME="inputform" ACTION="" METHOD="GET">
<table border="10" cellpadding="0" cellspacing="0" width="200" height="100" bgcolor="#CCCCCC" bordercolordark="blue" bordercolorlight="red">
<tr>
<td align="center" valign="middle">
<p><b>your INPUT:</b><br>
<br>
<INPUT TYPE="text" NAME="inputbox" VALUE="" maxlength="10" size="10" style="color:white; background-color:blue;"> &nbsp;<INPUT TYPE="button" NAME="button" Value="-- ok --" onClick="testResults(this.form)" style="color:yellow; background-color:blue;">
</p>
</td>
</tr>
</table>
</FORM>
</BODY>
</HTML>
inputbox with html

Image

a replacement for the "lifeless" InputRequester...

Posted: Thu Mar 02, 2006 10:27 am
by Rescator
Now now, you can do bette than that! Like this for example :P

Use same PB code as above,
but this html instead :twisted:

Code: Select all

<HTML id=dlgAbout  STYLE="width: 250; height: 150;">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<HEAD>
</HEAD>
<SCRIPT LANGUAGE="JavaScript">
function testResults (form) {
window.returnValue = form.inputbox.value+'\n'+form.inputbox2.value;
window.close()
}
</SCRIPT>
<BODY onload="self.focus(); document.inputform.inputbox.focus();">
<FORM NAME="inputform" ACTION="" METHOD="GET">
<table border="10" cellpadding="0" cellspacing="0" width="250" height="150" bgcolor="#CCCCCC" bordercolordark="blue" bordercolorlight="red">
<tr>
<td align="center" valign="middle">
<p><b>your INPUT:</b><br>
<br>
<INPUT TYPE="text" NAME="inputbox" VALUE="" maxlength="10" size="10" style="color:white; background-color:blue;">
<INPUT TYPE="text" NAME="inputbox2" VALUE="" maxlength="10" size="10" style="color:white; background-color:blue;"> &nbsp;<INPUT TYPE="button" NAME="button" Value="-- ok --" onClick="testResults(this.form)" style="color:yellow; background-color:blue;">
</p>
</td>
</tr>
</table>
</FORM>
</BODY>
</HTML>

Posted: Thu Mar 02, 2006 11:19 am
by PB
@Rescator: Your example is majorly flawed in two ways:

(1) If I click Okay, I get told that I cancelled, which is definitely not true.
(2) If I enter "123" and click Cancel, the value returned is still the default.

Back to the ol' drawing board for you. :)

Posted: Thu Mar 02, 2006 8:07 pm
by Rescator
Redo the last line to:

Code: Select all

If a$="default" : Debug "No change!" : Else : Debug a$ : EndIf

:lol:

Posted: Wed Oct 18, 2006 4:59 pm
by akj
I thought I would add my own twopennyworth to this thread by making a few changes that seemed useful:

1. Width and height parameters added. These are not the dimensions of the overall input box, but those of the text box containing the prompt string. If the width and height are both specified as zero, they default to 128 x 20, which is about the smallest useful size.

2. Instead of just being able to set the password flag, any #PB_String_xxx flag can now be set.
For example: #PB_String_UpperCase

3. The OK button has been moved further to the left (because I preferred the appearance of the input box to be symmetrical).

4. The input box no longer beeps each second when it loses the input focus (because the beeps annoyed me).

5. All gadget numbers are now generated by #PB_Any instead of being hardcoded as arbitrary numbers such as 997.

6. All variables are now declared in order to be EnableExplicit compliant.

Code: Select all

Procedure.s InputBox(txtw, txth, title$, prompt$, def$="", flags=0)
; A version of InputRequester() by BackupUser
; Modified by AKJ 18-Oct-06
; Downloaded: www.purebasic.fr/english/viewtopic.php?t=2412
; textw and txth are the outer dimensions of the prompt text gadget
; Available flags are:
;   #PB_String_{BorderLess  LowerCase  Numeric  Password  ReadOnly  Uppercase}
; Features:
; (1) Modal (locks the calling window until done)
; (2) Prompt area is larger
; (3) Prompt area supports multi-line text with Chr(13)
; (4) Cancel button in addition to OK button
; (5) Returns the default string (def$) if the Cancel button is pressed
; (6) Returns "" if an error occurs
; (7) Standard Windows look-And-feel
; (8) Plays the "question" prompt sound
; (9) Works with or without a calling window
;(10) Emulates the Visual Basic InputBox() command
;(11) Supports all #PB_String_xxx flags
Protected winBox, txtPrompt, strInput, butOK, butCancel ; Gadgets
Protected box, ev, id, ret, esc, a, thread1, thread2, text$=""
If txtw<128 : txtw=128 : EndIf ; To show buttons correctly
If txth<20 : txth = 20 : EndIf ; Height of a normal text line
winBox=OpenWindow(#PB_Any,0,0,txtw+13,txth+20+23+8*4,title$,#PB_Window_ScreenCentered)
box=WindowID(winBox)
If winBox And CreateGadgetList(box)
  txtPrompt=TextGadget(#PB_Any,6,8,txtw,txth,prompt$)
  If flags&#PB_String_Password=0 : flags|#ES_MULTILINE : EndIf
  strInput=StringGadget(#PB_Any,6,txth+8*2,txtw,20,def$,flags|#ES_AUTOVSCROLL)
  butOK=ButtonGadget(#PB_Any,6,txth+20+8*3,60,23,"OK") ; Set x=txtw-122 for button to be on the right
  butCancel=ButtonGadget(#PB_Any,txtw-54,txth+20+8*3,60,23,"Cancel")
  SendMessage_(GadgetID(strInput),#EM_SETSEL,0,Len(def$))
  GetAsyncKeyState_(#VK_RETURN) : GetAsyncKeyState_(#VK_ESCAPE)
  StickyWindow(winBox,#True) : SetForegroundWindow_(box) : SetActiveGadget(strInput) : MessageBeep_(#MB_ICONQUESTION)
  Repeat
    ev=WaitWindowEvent(1) : id=EventGadget() : ret=GetAsyncKeyState_(#VK_RETURN) : esc=GetAsyncKeyState_(#VK_ESCAPE)
    a=GetForegroundWindow_()
    If a<>box
      thread1=GetWindowThreadProcessId_(@a,0) : thread2=GetWindowThreadProcessId_(@box,0)
      If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
      SetForegroundWindow_(box) : Sleep_(1)
      If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf
      SetActiveGadget(strInput); !!! : MessageBeep_(#MB_ICONQUESTION)
    EndIf
  Until (ev=#PB_Event_Gadget And (id=butOK Or id=butCancel)) Or ret<>0 Or esc<>0 Or ev=#PB_Event_CloseWindow
  If id=butOK Or ret<>0 : text$=GetGadgetText(strInput) : Else : text$=def$ : EndIf
  CloseWindow(winBox)
EndIf
ProcedureReturn text$
EndProcedure

; Example using BackupUser's dimensions for the prompt text gadget
Debug InputBox(487, 70, "Test", "Enter something:", "default", #PB_String_UpperCase)