Page 2 of 5

Re: Intercept the *Return Key*

Posted: Wed Feb 01, 2012 11:02 pm
by MachineCode
Manual wrote:A shortcut generates a menu event (like a menu item) as most of them are used in conjunction with menus.
So, they're meant to be used with menus. :P

Re: Intercept the *Return Key*

Posted: Thu Feb 02, 2012 12:24 am
by Randy Walker
kenmo wrote::?: :?: :?:

Randy, am I overlooking something...? Why can't you use AddKeyboardShortcut() with #PB_Shortcut_Return for your needs?...
The only problem is if your window has a multiline text gadget or editor gadget... how do you still receive Return presses? My preferred solution is...
Not to put words in your mouth but, we can finish that sentence with ''a workaround, for lack of having a clear and defined rock solid means of intercepting use of the return key''

I also have a number of windows in my app. Seventeen to be somewhat precise,and the majority do have multi-line StringGadgets, which in itself is already a workaround I adopted long ago to help defeat the ding that accompanies use of the Return key while inside a StringGadget if it is left single line. My string gadgets either prompt the user for information or they are provided as a means to perform a search. I use Fkeys in more than half the windows. So far I haven't found any need to disable/re-enable any of them. I would hate to have to adopt the practice as another workaround for managing the Return key.

Re: Intercept the *Return Key*

Posted: Thu Feb 02, 2012 12:43 am
by kenmo
You aren't putting words in my mouth... I already put those words in my mouth. :) I ended my post with:
It sounds like a workaround, but it is simple to implement and seems to work fine.
And I guess that's my point... AddKeyboardShortcut() + a little bit of bookkeeping is one way (possibly the best way, currently) to accomplish your goal using native PB code. That's in addition to callbacks and OS-specific API/constants, which you already know about.

It sounds like the only thing you would not consider a "workaround" is a native KeyDown event in PB, or an EventType_ReturnKey, or similar. In that case, it sounds like you want a Feature Request rather than a Coding Question. (And that's fine, it would actually be very useful beyond just the Return key.)

But of course, in the end, it would be compiled to OS-specific code behind the scenes... just saves us some manual coding.


PS. I was just looking through the docs... didn't StringGadget used to have a MultiLine constant? Or has EditorGadget/ScintillaGadget always been the proper way to do multiline text?

Re: Intercept the *Return Key*

Posted: Thu Feb 02, 2012 2:30 am
by Randy Walker
kenmo wrote:PS. I was just looking through the docs... didn't StringGadget used to have a MultiLine constant? Or has EditorGadget/ScintillaGadget always been the proper way to do multiline text?
Yes, I saw somewhere that PB_multiline thingy was removed a long while back. I forget where I saw the comment.

Re: Intercept the *Return Key*

Posted: Fri Feb 03, 2012 2:33 am
by em_uk
This method always works for me (rough version of the idea atleast) :

Code: Select all

return_key = 1
quit_event = 2
button_return=3
OpenWindow(0,#Null,#Null,400,200,"HAI",#PB_Window_ScreenCentered)
StringGadget(1,5,5,300,20,"Sting Field 1")
StringGadget(2,5,35,300,20,"2 Field String")
ButtonGadget(3,5,60,70,30,"Clear",#PB_Button_Default)
AddKeyboardShortcut(0,#PB_Shortcut_Return,return_key)
AddKeyboardShortcut(0,#PB_Shortcut_Escape,quit_event)
AddKeyboardShortcut(0,#PB_Shortcut_Return,button_return)


SetActiveGadget(1)

Repeat
  
  event=WaitWindowEvent()
  eventg=EventGadget()
  
  Select event
      
    Case #PB_Event_Gadget
      
      Select eventg
          
        Case 1,2
          Select EventType()
              
            Case #PB_EventType_Focus
              
              AddKeyboardShortcut(0,#PB_Shortcut_Return, return_key)
              
            Case #PB_EventType_LostFocus
              RemoveKeyboardShortcut(0,#PB_Shortcut_Return)
              AddKeyboardShortcut(0,#PB_Shortcut_Return,button_return)
          EndSelect
          
        Case 3

          AddKeyboardShortcut(0,#PB_Shortcut_Return,button_return)
          MessageRequester("Easy",GetGadgetText(1)+" See?")
          SetActiveGadget(1)
      EndSelect
      
    Case #PB_Event_Menu

      Select eventg
          
        Case return_key 
          
          Selected=GetActiveGadget()+1
          If (Selected)>3 : SetActiveGadget(Selected):EndIf
          SetActiveGadget(Selected) : SetGadgetState(Selected,1)

        Case button_return
          MessageRequester("Easy",GetGadgetText(1)+" See?")
          SetActiveGadget(1)
          
        Case quit_event
          Quit=1
          
      EndSelect
      
  EndSelect
 ; Debug event
Until Quit=1

Re: Intercept the *Return Key*

Posted: Fri Feb 03, 2012 5:28 am
by skywalk
Respect multi-line EditorGadget without callbacks or removal of keyboard shortcuts.
Windows only...

Code: Select all

Global numMenuEntries = 4  ; Keep track of total menu items if you have any
Global return_key    = numMenuEntries + 1
Global quit_event    = numMenuEntries + 2
Procedure.i gad_NoTabStop(hndGad.i)
  Protected.i Style = GetWindowLongPtr_(hndGad, #GWL_STYLE)
  SetWindowLongPtr_(hndGad, #GWL_STYLE, Style & ((-1) - #WS_TABSTOP))
  ProcedureReturn hndGad
EndProcedure

Procedure Win0_Open()
  OpenWindow(0,#Null,#Null,400,200,"Hit Escape to Quit",#PB_Window_ScreenCentered)
  StringGadget(1,5,5,300,20,"String 1")
  StringGadget(2,5,35,300,20,"String 2")
  ButtonGadget(3,5,60,120,30,"Tab to here, then Enter",#PB_Button_Default)
  EditorGadget(4,5,110,300,60,#ES_MULTILINE)
  AddGadgetItem(4,-1,"Edit 1"+#CRLF$+"Hit Enter Here...Edit 1")
  gad_NoTabStop(GadgetID(4))
  AddKeyboardShortcut(0,#PB_Shortcut_Return,return_key)
  AddKeyboardShortcut(0,#PB_Shortcut_Escape,quit_event)
  If CreateMenu(0, WindowID(0))    ; menu creation starts....
    MenuTitle("Project")
    MenuItem(1, "Open"   +Chr(9)+"Ctrl+O")
    MenuItem(2, "Save"   +Chr(9)+"Ctrl+S")
    MenuItem(3, "Save as"+Chr(9)+"Ctrl+A")
    MenuItem(4, "Close"  +Chr(9)+"Ctrl+C")
  EndIf
  SetActiveGadget(1)
EndProcedure

Procedure Win0_Main()
  Repeat
    evWW = WaitWindowEvent()
    Select evWW
    Case #PB_Event_Gadget
      evG = EventGadget()
      Select evG
      Case 1,2
      Case 3
        MessageRequester("Clicked",GetGadgetText(3))
      EndSelect
    Case #PB_Event_Menu
      evM = EventMenu()
      Select evM
      Case return_key
        evG = GetActiveGadget()
        If evG = 4
          keybd_event_(#VK_SHIFT,0,0,0)
          keybd_event_(#VK_RETURN,0,0,0)
          keybd_event_(#VK_RETURN,0,#KEYEVENTF_KEYUP,0)
          keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0)
        Else
          MessageRequester("Return Key From:",GetGadgetText(evG))
        EndIf
      Case 4,quit_event
        Quit = 1
      EndSelect
    EndSelect
  Until Quit = 1
EndProcedure
Win0_Open()
Win0_Main()

Re: Intercept the *Return Key*

Posted: Fri Feb 03, 2012 11:52 am
by Randy Walker
Ok people... Get Ready ! ! ! :lol:

I'm getting my next 'Tips_n_Tricks' post lined up for submission, and boyyyyyy let me tell you. Its a whopper of a soulution. Centers on the use of the AddShortcutKey since that seem to be the general cencensus for non-API non-CAllBack cross platform operations. You're going to roll your eyes, and that's ok. Maybe over there we can snare all the seasoned eyeballs into the discussion and get this dilemma ironed out into something ''practical''.

Re: Intercept the *Return Key*

Posted: Mon Feb 06, 2012 10:10 am
by Randy Walker
And here it is. As promised. The solution to beat all solutions :lol: (tongue in cheek) AND ... its cross platform, but it is also still just another workaround :? :( :cry:
viewtopic.php?f=12&t=49086&sid=b68c4e7d ... 4e11b4ce97
Also, submitted a Feature Request:
viewtopic.php?f=3&t=49089&sid=b68c4e7d9 ... 4e11b4ce97

Re: Intercept the *Return Key*

Posted: Mon Feb 06, 2012 11:56 am
by MachineCode
Randy Walker wrote:I have been forced to add a CallBack and things just went downhill from there. Can't seem to rely on WaitWindowEvent() = #WM_KEYDOWN checking any more.
#WM_KEYDOWN works fine with a Callback. Sorry to tell you this, but you're your own worst enemy. I'd say you just currently have a bad coding style if nothing's "working" when you add a Callback; and I truly, honestly say that without any intent of malice, or to cause offence, or to make you angry. Please don't take it the wrong way.

Re: Intercept the *Return Key*

Posted: Mon Feb 06, 2012 1:05 pm
by Randy Walker
MachineCode wrote:
Randy Walker wrote:I have been forced to add a CallBack and things just went downhill from there. Can't seem to rely on WaitWindowEvent() = #WM_KEYDOWN checking any more.
#WM_KEYDOWN works fine with a Callback. Sorry to tell you this, but you're your own worst enemy. I'd say you just currently have a bad coding style if nothing's "working" when you add a Callback; and I truly, honestly say that without any intent of malice, or to cause offence, or to make you angry. Please don't take it the wrong way.
Ok, so what you are saying here is, if I take my code from v4.20 that was working fine and I compile it using the v4.60 compiler and half my controls stop working then I have bad coding style?

While I can easily agree that I am my own worst enemy, I have to say there is something wrong in your logic. If the APIs compile and work fine in 4.20 then I expect they sould compile and work in v4.60 >> after applying changes ordained by PureBasic change logs, and only making said changes as specified in that change log.

If you are judging me on my last (ridiculous) post over in 'Tips-n-Trick' where I was using evey possible AddKeyboardShortcut then you missed the joke entirely. That was a satire on the total absence of any practical facility in PureBasic to catch keyboard input to a StringGadget. I think, even if you re-examine my basic code structure (ignoring the AddKeyboardShortcut non-sense) you will find my coding practices are very orderly. And, no. I'm not offended, angry and not taking it the wrong way. I like feedback, so thank you for that.

Re: Intercept the *Return Key*

Posted: Mon Feb 06, 2012 1:21 pm
by MachineCode
Randy Walker wrote:if I take my code from v4.20 that was working fine and I compile it using the v4.60 compiler and half my controls stop working then I have bad coding style?
Well, whether v4.60 can actually break previously working code from v4.20 is something that would have be checked by seeing your code. It's very possible that v4.60 does break something in your coding logic.

Re: Intercept the *Return Key*

Posted: Mon Feb 06, 2012 1:23 pm
by ts-soft
Windows Only,
here a small example that emulate old dialog behavior.
Return for buttons and stringgadgets.

Code: Select all

EnableExplicit

Procedure EmulateDialogCallback(hWnd, uMsg, wParam, lParam)
  Protected oldproc = GetProp_(hWnd, "oldproc")
 
  Select uMsg
    Case #WM_NCDESTROY
      RemoveProp_(hWnd, "oldproc")
    Case #WM_KEYDOWN
      Select GadgetType(GetDlgCtrlID_(hWnd))
        Case #PB_GadgetType_Button, #PB_GadgetType_ButtonImage
          If wParam = #VK_RETURN
            SendMessage_(hWnd, #BM_CLICK , 0, 0)
            ProcedureReturn 0
          EndIf
        Case #PB_GadgetType_String
          If wParam = #VK_RETURN
            SetFocus_(GetNextDlgTabItem_(GetParent_(hWnd), hWnd, #False))
            ProcedureReturn 0
          EndIf
        Case #PB_GadgetType_Option
          If wParam = #VK_DOWN
            SendMessage_(GetNextDlgGroupItem_(GetParent_(hWnd), hWnd, #False), #BM_CLICK , 0, 0)
            ProcedureReturn 0
          ElseIf wparam = #VK_UP
            SendMessage_(GetNextDlgGroupItem_(GetParent_(hWnd), hWnd, #True), #BM_CLICK , 0, 0)
            ProcedureReturn 0
          EndIf
      EndSelect
  EndSelect
 
  ProcedureReturn CallWindowProc_(oldproc, hWnd, uMsg, wParam, lParam)
EndProcedure

Procedure EmulateDialog(ID)
  Protected oldproc = SetWindowLongPtr_(GadgetID(ID), #GWL_WNDPROC, @EmulateDialogCallback())
  ProcedureReturn SetProp_(GadgetID(ID), "oldproc", oldproc)
EndProcedure

Procedure InitEmulateWin(ID)
  ProcedureReturn SendMessage_(WindowID(ID), #WM_CHANGEUISTATE, 2 | (1 << 16), 0)
EndProcedure

; Example

Define i
OpenWindow(0, 0, 0, 222, 200, "ButtonGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   
ButtonGadget(0, 10, 10, 200, 20, "Default Button")
StringGadget(1, 10, 40, 200, 20, "")
StringGadget(2, 10, 70, 200, 20, "")
OptionGadget(3, 10, 100, 60, 20, "Option 1")
OptionGadget(4, 10, 130, 60, 20, "Option 2")
OptionGadget(5, 10, 160, 60, 20, "Option 3")
SetGadgetState(3, 1)
SetActiveGadget(0)
For i = 0 To 5
  EmulateDialog(i)
Next

InitEmulateWin(0)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow : Break
    Case #PB_Event_Gadget
      Debug "Gadget: " + Str(EventGadget()) + " : Type: " + Str(EventType())
  EndSelect
ForEver

Re: Intercept the *Return Key*

Posted: Mon Feb 06, 2012 2:07 pm
by Randy Walker
@ts-soft ... Looks complicated :D
All contributions welcome, and thanks for the feedback :wink:

Re: Intercept the *Return Key*

Posted: Wed Feb 08, 2012 11:51 pm
by Slyvnr
Randy Walker wrote:
Can we get a show of hands from the audience please? How many of you would call this a workaround?

Code: Select all

          Case #PB_Event_CloseWindow
            Quit = 1
I thought that was the standard way of doing the [X} close Window and not a work around.

Slyvnr

Re: Intercept the *Return Key*

Posted: Thu Feb 09, 2012 1:24 am
by Randy Walker
Slyvnr wrote:
Randy Walker wrote:
Can we get a show of hands from the audience please? How many of you would call this a workaround?

Code: Select all

          Case #PB_Event_CloseWindow
            Quit = 1
I thought that was the standard way of doing the [X} close Window and not a work around.

Slyvnr
This is a direct way to do the [x] close Window:

Code: Select all

  Repeat
    Event = WaitWindowEvent()
  
  Until Event = #PB_Event_CloseWindow  ; If the user has pressed on the close button
And this is some silly workaround (or perceived shortcut) some people have gotten into the habit of doing:

Code: Select all

  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_CloseWindow  ; If the user has pressed on the close button
      quit = 1
    EndIf
    
  Until quit = 1
If for some reason you encounter a condition that requires the application to close then this would be more appropriate:

Code: Select all

  Repeat
    Event = WaitWindowEvent()
    
    If MyRasberriesTurnBlue.l = #True
      Event = #PB_Event_CloseWindow
    EndIf
  
  Until Event = #PB_Event_CloseWindow  ; If the user has pressed on the close button
Always more than one way to skin a cat. I imagine there are even some people that would say Rube Goldburg is a master of efficiency. I think the direct way is more appropriate, if not more proper.