Page 1 of 1
Porting Windows program
Posted: Fri Feb 27, 2015 5:20 pm
by harkon
I am new to PB on Linux so if I come of a bit new, then I appologize.
I am having a great deal of difficulty in figuring out how to create similar GTK calls as to what my windows calls were.
I need to get an set a selection in a string gadget. The lines look like this.
SendMessage_(HandleWindow, #EM_GETSEL, @sStart, @sEnd)
;this gets the start and end positions of the selected text
and
SendMessage_(HandleWindow, #EM_SETSEL, sStart, -1)
;selects text in the string gadget from the start till the end of the string.
I need to emulate this behaviour in Linux. I have DevHelp installed and got some good insight but I can't get a lot of this to work. I must be on the wrong track.
Any help is greatly appreciated.
Re: Porting Windows program
Posted: Fri Feb 27, 2015 5:37 pm
by Shardik
You should take a look into my
list of links to cross-platform code examples. There you will also find links to StringGadget examples which demonstrate how to get and set selected text or how to set the cursor position...
An alternative when looking for Linux API solutions would be to take a look into Oma's
Linux API Libraries...
Re: Porting Windows program
Posted: Fri Feb 27, 2015 6:21 pm
by harkon
This looks like what I've been looking for.
Thanks for your help.
Re: Porting Windows program
Posted: Mon Mar 02, 2015 9:30 pm
by harkon
Currently I use the following routine to get the last keyboard input;
Code: Select all
Structure TagMSG
hwnd.l
message.i
wParam.w
lParam.l
time.l
pt.l
EndStructure
Procedure GetLastKey.w(gadget_ID.l)
Define Result.i
Define LastKey.w
Define MSG.TagMSG
Result=GetMessage_(MSG,HandleWindow,#WM_KEYFIRST,#WM_KEYLAST)
LastKey=MSG\wParam
ProcedureReturn LastKey
EndProcedure
This works well to get the last key pressed. I found code to do this using a callback function but if I use this then I really probably should rewrite the Windows specific part of this to accomodate. There's a lot going on and would rather, if possible of course, just get the last key pressed to make for easier universal code.
The GTK callback code example looks like this;
Code: Select all
;======================================================================
; Module/File: Keys_GetData.pb
; Function: Get key and shift - Linux
; Author: Omi
; Date: Dec. 18, 2014
; Version: 0.2
; Target Compiler: PureBasic 5.22/5.30
; Target OS: (X/K)ubuntu ascii/uni, 32/64
; License: Free, unrestricted, no warranty
;======================================================================
;Shift-States: Bit (depends on installation)
; 0 = [Shift]
; 1 = [CapsLock]
; 2 = [Control]
; 3 = [Alt]
; 4 = [NumLock]
; 5 =
; 6 =
; 7 = [AltGr]
; 8 =
;
;26 = [Menue]
#MainWin= 0
ImportC ""
g_signal_connect(*instance, detailed_signal.p-ascii, *c_handler, *data, destroy= 0, flags= 0) As "g_signal_connect_data"
EndImport
Global.i gEvent
ProcedureC KeyPressCallback(*widget, *event.GdkEventKey, *udata)
Protected.i I, State, Pressed
Protected.a KeyAsc
Protected.l KeyWord
Protected.s StateKeys, StateNames= "[Shift] [CapsLock] [Control] [Alt] [NumLock] [] [] [AltGr]"
Pressed= *event\type
KeyAsc = *event\keyval & $FF
KeyWord= *event\keyval & $FFFF
State = *event\state
For I= 0 To 7
If (State >> I) & 1
StateKeys+ StringField(StateNames, I+ 1, " ")
EndIf
Next I
If KeyWord & $8000
StateKeys+ "[Numberpad]"
;(1) auch Bit 7 von KeyAsc gesetzt => ausblenden KeyAsc & $7F
EndIf
Debug #DOUBLEQUOTE$ + PeekS(*event\string) + #DOUBLEQUOTE$ + " = BYTE (ASC): " + Str(KeyAsc) + "/" + Str(KeyAsc & $7F) + ", WORD: " + Str(KeyWord)
Debug #DOUBLEQUOTE$ + " = BYTE (ASC): " + Str(KeyAsc) + "/" + Str(KeyAsc & $7F) + ", WORD: " + Str(KeyWord)
Debug "State: " + Str(State) + " = " + StateKeys
;Debug "Pressed: " + Str(Pressed)
Debug ""
EndProcedure
If OpenWindow(#MainWin, #PB_Any, #PB_Any, 200, 100, "keyPress to debug")
g_signal_connect(WindowID(#MainWin), "key_press_event", @KeyPressCallback(), #Null)
Repeat
gEvent = WaitWindowEvent()
Until gEvent = #PB_Event_CloseWindow
EndIf
For the life of me I cannot get to where I can find the data structure and method to call in order to make this something I can call on demand.
Re: Porting Windows program
Posted: Tue Mar 03, 2015 12:59 pm
by Shardik
harkon wrote:For the life of me I cannot get to where I can find the data structure and method to call in order to make this something I can call on demand.
Actually it's very easy: just use a global or shared variable in your callback to store the last key pressed...
For your conveniance I have put together the following code example which uses a specific callback for Windows and Linux to detect a keypress and store that value in the variable Key. The event loop compares the variable Key (from the callbacks) with a variable LastKey. Whenever they are different, the content of variable LastKey is set to the actual content of variable Key and displayed in the StatusBar:
Code: Select all
EnableExplicit
Define Key.S
Define LastKey.S
OpenWindow(0, 100, 100, 200, 65, "Last key pressed")
StringGadget(0, 10, 10, 180, 25, "")
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
ImportC ""
g_signal_connect_data(*Instance, SignalName.P-UTF8, *Callback, UserData.I, Destroy = 0, Flags = 0)
EndImport
ProcedureC KeyPressCallback(*Widget.GtkWidget, *Event.GdkEventKey, *UserData)
Shared Key.S
Select *Event\keyval
Case #GDK_BackSpace
Key = "Backspace"
Case #GDK_Shift_L
Key = "Left Shift"
Case #GDK_Shift_R
Key = "Right Shift"
Case #GDK_Control_L
Key = "Left Ctrl"
Case #GDK_Control_R
Key = "Right Ctrl"
Case #GDK_Alt_L
Key = "Left Alt"
Case #GDK_Alt_R
Key = "Right Alt"
Case #GDK_Return
Key = "Return"
Case #GDK_space
Key = "Space"
Default
Key = Chr(*Event\keyval)
EndSelect
EndProcedure
g_signal_connect_data(WindowID(0), "key_press_event", @KeyPressCallback(), 0)
CompilerCase #PB_OS_Windows
Define DefaultStringGadgetCallback.I
Procedure CustomStringGadgetCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
Shared DefaultStringGadgetCallback.I
Shared Key.S
If Msg = #WM_KEYUP
Select WParam
Case #VK_BACK
Key = "Backspace"
Case #VK_SHIFT
Key = "Shift"
Case #VK_CONTROL
Key = "Ctrl"
Case #VK_MENU
Key = "Alt"
Case #VK_SPACE
Key = "Space"
Case #VK_RETURN
Key = "Return"
Default
Key = Chr(WParam)
EndSelect
EndIf
ProcedureReturn CallWindowProc_(DefaultStringGadgetCallback, WindowHandle, Msg, WParam, LParam)
EndProcedure
DefaultStringGadgetCallback = SetWindowLongPtr_(GadgetID(0), #GWL_WNDPROC, @CustomStringGadgetCallback())
CompilerEndSelect
CreateStatusBar(0, WindowID(0))
AddStatusBarField(#PB_Ignore)
SetActiveGadget(0)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
EndSelect
If LastKey <> Key
LastKey = Key
StatusBarText(0, 0, "Last key: " + LastKey, #PB_StatusBar_Center)
EndIf
ForEver
Re: Porting Windows program
Posted: Tue Mar 03, 2015 4:05 pm
by harkon
Thanks for the help. I really was hoping to be able to do this withour a callback function, but I can do the extra work to do this right. The whole thing should probably get a good rewrite anyway.
Once you use the;
g_signal_connect_data(WindowID(0), "key_press_event", @KeyPressCallback(), 0)
How do I 'unconnect'? I will need the same function in different windows and for different string fields. Do I just continue to add connections to gadgets and do they all get destroyed on exit, or do I need to set and unset callback connections? Hope this makes sense.
Re: Porting Windows program
Posted: Tue Mar 03, 2015 8:01 pm
by Shardik
harkon wrote:Once you use the;
g_signal_connect_data(WindowID(0), "key_press_event", @KeyPressCallback(), 0)
How do I 'unconnect'?
You simply set the callback address to 0:
Code: Select all
g_signal_connect_data(WindowID(0), "key_press_event", 0, 0)
But it isn't necessary to reset the callback. You might as well set the callback to each Gagdet for which you want to capture the pressed keys by replacing WindowID() with GadgetID().
For your conveniance I have again put together a code example which captures and displays each key press of a StringGadget and of an EditorGadget. The new example is again running equally well in Windows and Linux and displays in the StatusBar the last key pressed and the respective Gadget. For the sake of clarity I have removed all the evaluations of modifier keys like <Ctrl> or <Alt> in both callbacks...
Code: Select all
EnableExplicit
Enumeration
#StringGadget
#EditorGadget
EndEnumeration
Define Key.S
Define LastKey.S
OpenWindow(0, 100, 100, 200, 140, "Last key pressed")
StringGadget(#StringGadget, 10, 10, 180, 25, "")
EditorGadget(#EditorGadget, 10, 45, 180, 60)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
ImportC ""
g_signal_connect_data(*Instance, SignalName.P-UTF8, *Callback, UserData.I, Destroy = 0, Flags = 0)
EndImport
ProcedureC KeyPressCallback(*Widget.GtkWidget, *Event.GdkEventKey, *UserData)
Shared Key.S
Key = Chr(*Event\keyval)
EndProcedure
g_signal_connect_data(GadgetID(#StringGadget), "key_press_event", @KeyPressCallback(), 0)
g_signal_connect_data(GadgetID(#EditorGadget), "key_press_event", @KeyPressCallback(), 0)
CompilerCase #PB_OS_Windows
Define DefaultEditorGadgetCallback.I
Define DefaultStringGadgetCallback.I
Procedure KeyPressCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
Shared DefaultEditorGadgetCallback.I
Shared DefaultStringGadgetCallback.I
Shared Key.S
Protected DefaultCallback.I
Key = Chr(WParam)
Select WindowHandle
Case GadgetID(#EditorGadget)
DefaultCallback = DefaultEditorGadgetCallback
Case GadgetID(#StringGadget)
DefaultCallback = DefaultStringGadgetCallback
EndSelect
ProcedureReturn CallWindowProc_(DefaultCallback, WindowHandle, Msg, WParam, LParam)
EndProcedure
DefaultStringGadgetCallback = SetWindowLongPtr_(GadgetID(#StringGadget), #GWL_WNDPROC, @KeyPressCallback())
DefaultEditorGadgetCallback = SetWindowLongPtr_(GadgetID(#EditorGadget), #GWL_WNDPROC, @KeyPressCallback())
CompilerEndSelect
CreateStatusBar(0, WindowID(0))
AddStatusBarField(#PB_Ignore)
SetActiveGadget(#StringGadget)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
EndSelect
If LastKey <> Key
LastKey = Key
StatusBarText(0, 0, "Gadget: " + GetActiveGadget() +
", Key: " + LastKey, #PB_StatusBar_Center)
EndIf
ForEver
Re: Porting Windows program
Posted: Wed Mar 04, 2015 2:14 am
by harkon
Thank you so very much for your help, it is greatly appreciated. I think I have enough to get going on this. Often learning a new way of doing things, and with the docs on GTK API being quite advanced. these examples make understanding very visual, which is a great way to learn.