|
Post by (X) on Aug 13, 2023 17:33:12 GMT 1
GFA coders can create their own GFA Editor Extensions!
How does this work?
Yes, but can the GLL call up a "form" or the like; with buttons, labels, comboboxes etc?
YES!
And, look for more posts labelled: "TIP:", "INFO:", "DEMO:" in the various sections of this forum...
|
|
|
Post by (X) on Aug 14, 2023 2:35:06 GMT 1
This is a small piece of the puzzle. I am trying to figure out how to handle 'events' that 'happen' on the Dialog form.
'################################################################################# ' ' DISCLAIMER: THIS CODE IS OFFERED AS IS FOR EDUCATIONAL PURPOSES. ' YOU ARE FREE TO USE, COPY AND DISTRIBUTE. ' THE USE OF THIS CODE IS AT YOUR OWN RISK. ' I ACCEPT NO LIABILITY NOR MAKE ANY CLAIM OF ' CORRECTNESS OR SUITABILITY IN PART OR IN WHOLE. ' '################################################################################# ' ' FILENAME GFA_APP_D__GLL_Dialog.G32 ' ' DESCRIPTION A demo of using a Dialog 'Form' from a GLL (GFA Editor Extension) ' ' AUTHOR (X) ' EMAIL xman.gb32@gmail.com ' WEBSITE https://gfabasic32.blogspot.com/ ' FORUM https://gb32.proboards.com/ ' STARTED 2023-08-13 ' UPDATED <ISO date> ' '
Type NMHDR hwndFrom As Long idfrom As Long code As Long EndType
Sub Gfa_Second 'Dlg_1_MessageProc(Dlg_1.hWnd, _Mess, _wParam, _lParam) _Win$(Dlg(1, 102)) = Now$ DoEvents EndSub
Sub Gfa_App_D // D for Dialog P_Dialog_Test EndSub
Proc P_Dialog_Test '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Create a 'Dialog' control, a somewhat early incarnation of a 'Form'. ' ' NOTES: ' 1) The Dialog command is useful for converting GFA-BASIC 16 programs and ' in GLL extensions. ' 2) In a normal program use Form instead. ' 3) OCX types are not allowed in a GLL. ' Local dlgf&, s%, v% Const STYLE1 = WS_TABSTOP Const STYLE2 = BS_DEFPUSHBUTTON | WS_TABSTOP Const STYLE3 = BS_GROUPBOX | WS_TABSTOP Const STYLE4 = BS_AUTORADIOBUTTON | WS_TABSTOP Const STYLE5 = BS_AUTOCHECKBOX | WS_TABSTOP Const STYLE6 = ES_UPPERCASE | WS_TABSTOP | WS_BORDER Const STYLE7 = LBS_NOTIFY | LBS_SORT | LBS_STANDARD | WS_BORDER | WS_VSCROLL Const STYLE8 = CBS_DROPDOWN | CBS_SORT | CBS_HASSTRINGS | WS_VSCROLL Const STYLE9 = SB_CTL | SB_BOTTOM Const WS_OVERLAPPEDWINDOW = 0xCF0000 DlgBase Pixel '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' DIALOG SYNTAX: ' ' Dialog hd%, x%, y%, w%, h%, tit$ [, flag% [, height%, font$]] ' Dialog # 1 , 10, 10, 400, 400, "Dlg Test", WS_OVERLAPPEDWINDOW EditText "Test" , 100, 10, 10, 100, 30, STYLE6 PushButton "PUSHBUTTON" , 101, 10, 50, 100, 30, STYLE1 StatusCtrl "" , 102, 0, 340, 400, 30, EndDialog ShowDialog # 1 ~SetFocus(DlgItem(1, 100)) EndProc
Sub Dlg_1_MessageProc(hWnd%, Mess%, wParam%, lParam%, retval%, ValidRet?) Dim hdr As Pointer NMHDR Switch Mess Case WM_NOTIFY Pointer(hdr) = lParam Trace hdr EndSwitch EndSub
I need to find out how I can 'see' the messages as events are triggered on the Dialog form.
|
|
|
Post by (X) on Aug 14, 2023 4:11:17 GMT 1
This Help section seems very promissing: I stumbled upon this when looking up information on the Message statement in the Help file. This seems to work just fine. The tricky part is going to be setting up the message "Select Case" statements to respond to the message codes as required. I am encouraged. "We've come a long way baby!"
|
|
|
Post by scalion on Aug 14, 2023 20:27:32 GMT 1
To prevent multiple call to a same dialog in gll a way is to use the Gfa_MenuEnable() property. Example :
' Test Dialog in GLL ' Thank's to (X) Sub Gfa_Init Global IdxMenuTestDialog IdxMenuTestDialog = Gfa_AddMenu("IdxMenuTestDialog", IdxMenuTestDialog_func) Gfa_MenuDesc(IdxMenuTestDialog) = "IdxMenuTestDialog" End Sub Proc IdxMenuTestDialog_func(Index%) Local Const STYLE1 = WS_TABSTOP Local Const STYLE2 = BS_DEFPUSHBUTTON | WS_TABSTOP Local Const STYLE3 = BS_GROUPBOX | WS_TABSTOP Local Const STYLE4 = BS_AUTORADIOBUTTON | WS_TABSTOP Local Const STYLE5 = BS_AUTOCHECKBOX | WS_TABSTOP Local Const STYLE6 = ES_UPPERCASE | WS_BORDER | WS_TABSTOP Local Const STYLE7 = LBS_NOTIFY | LBS_SORT | LBS_STANDARD | WS_BORDER | WS_VSCROLL Local Const STYLE8 = CBS_DROPDOWN | CBS_SORT | CBS_HASSTRINGS | WS_VSCROLL Local Const WS_OVERLAPPEDWINDOW = 0xCF0000 If Gfa_MenuEnable(IdxMenuTestDialog) = True Gfa_MenuEnable(IdxMenuTestDialog) = False DlgBase Pixel Dialog # 1, 10, 10, 400, 400, "Dlg Test", WS_OVERLAPPEDWINDOW EditText "Test", 100, 10, 10, 100, 30, STYLE6 PushButton "Ok", 102, 100, 300, 200, 40, BS_PUSHBUTTON EndDialog ShowDialog # 1 ~SetFocus(DlgItem(1, 100)) EndIf EndProc Sub Gfa_CB(hDlg%, Msg%, wParam%, lParam%, RetVal%, ValidRet?) If hDlg% = Dlg(1) Handle_Dlg1(hDlg%, Msg%, wParam%, lParam%, RetVal%, ValidRet?) EndIf EndSub
Sub Handle_Dlg1(hDlg%, Msg%, wParam%, lParam%, RetVal%, ValidRet?) Select Msg Case WM_COMMAND If wParam = 102 Message "Command Button Ok Pressed and EditText is : " & _Win$(DlgItem(1, 100)) CloseDialog # 1 Gfa_MenuEnable(IdxMenuTestDialog) = True EndIf EndSelect EndSub
|
|
|
Post by (X) on Aug 14, 2023 23:18:45 GMT 1
One of the first things I thought of doing with this 'new found power' is a 'color selection form' that lets you specify HSL and the GLL code types out an RGB(r,g,b) value.
There are many many more possibilities and one major one will be to generate a sequence of events that compiles and implements a newly created GLL automatically instead of having to do so manually over and over again.
|
|
|
Post by (X) on Aug 15, 2023 19:03:40 GMT 1
I am just getting oriented, so, I've added lots of notes and comments. I am feeling like I am getting more and more in control of the program flow and can see this becoming very useful.
A word of caution about an easily contructed runaway condition.
It is worth noting that if you were to add a message 'packet' string as an item entry into a ListBox, for later inspection, as I am doing here, then, you have to be careful, because, if you were to start inserting/adding the messages related to the ListBox itself, then, this would cause an infinite loop of messages being dumped into the list box. Every time you add an item to a ListBox, then, this itself generates a corresponding Window Message! And yes; I am speaking from experience.
This code is a bit more organised and I am starting to see the main program flow more clearly.
'################################################################################# ' ' DISCLAIMER: THIS CODE IS OFFERED AS IS FOR EDUCATIONAL PURPOSES. ' YOU ARE FREE TO USE, COPY AND DISTRIBUTE. ' THE USE OF THIS CODE IS AT YOUR OWN RISK. ' I ACCEPT NO LIABILITY NOR MAKE ANY CLAIM OF ' CORRECTNESS OR SUITABILITY IN PART OR IN WHOLE. ' '################################################################################# ' ' FILENAME GFA_APP_D__GLL_Dialog.G32 ' ' DESCRIPTION A demo of using a Dialog 'Form' from a GLL (GFA Editor Extension) ' ' AUTHOR (X) ' EMAIL xman.gb32@gmail.com ' WEBSITE https://gfabasic32.blogspot.com/ ' FORUM https://gb32.proboards.com/ ' STARTED 2023-08-13 Just dipping my big toe into this great sea of possibilities. ' UPDATED 2023-08-15 This is coming along OK. I am making a lot of notes ' to cement the concepts in my mind. The message handler routine is ' the key to responding to the user interactions and making this code ' usefull and effective. ' ' Sub Gfa_Init Declare Function MoveWindow Lib "user32" ( _ ByVal hWnd As Long, _ ByVal x As Long, _ ByVal y As Long, _ ByVal nWidth As Long, _ ByVal nHeight As Long, _ ByVal bRepaint As Long) As Long EndSub Sub Gfa_Second _Win$(Dlg(1, iSB)) = Now$ EndSub
Sub Gfa_App_D // D for Dialog P_Dialog_Test EndSub
Proc P_Dialog_Test '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Create a 'Dialog' control, a somewhat early incarnation of a 'Form'. ' ' NOTES: ' 1) The Dialog command is useful for converting GFA-BASIC 16 programs and ' in GLL extensions. ' 2) In a normal program use Form instead. ' 3) OCX types are not allowed in a GLL. ' Const STYLE1 = WS_TABSTOP Const STYLE2 = BS_DEFPUSHBUTTON | WS_TABSTOP Const STYLE3 = BS_GROUPBOX | WS_TABSTOP Const STYLE4 = BS_AUTORADIOBUTTON | WS_TABSTOP Const STYLE5 = BS_AUTOCHECKBOX | WS_TABSTOP Const STYLE6 = ES_UPPERCASE | WS_TABSTOP | WS_BORDER Const STYLE7 = LBS_NOTIFY | LBS_SORT | LBS_STANDARD | WS_BORDER | WS_VSCROLL Const STYLE8 = CBS_DROPDOWN | CBS_SORT | CBS_HASSTRINGS | WS_VSCROLL Const STYLE9 = SB_CTL | SB_BOTTOM Const WS_OVERLAPPEDWINDOW = 0xCF0000 Global Long DLx = 10, DLy = 10, DLw = 400, DLh = 400 Global Long Ctrl_Id = 100 Global Long iED = Ctrl_Id, EDx = 10, EDy = 10, EDw = DLw - 20, EDh = 30 Ctrl_Id++ Global Long iPB = Ctrl_Id, PBx = 10, PBy = EDy + EDh + 10, PBw = DLw - 20, PBh = 30 Ctrl_Id++ Global Long iLB = Ctrl_Id, LBx = 10, LBy = PBy + PBh + 10, LBw = DLw - 20, LBh = DLh - 130 Ctrl_Id++ Global Long iSB = Ctrl_Id, SBx = 10, SBy = DLh - 30, SBw = DLw - 20, SBh = 30 Ctrl_Id++ 'DlgBase Pixel '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' DIALOG SYNTAX: ' ' Dialog hd%, x%, y%, w%, h%, tit$ [, flag% [, height%, font$]] ' Dialog # 1 , DLx, DLy, DLw, DLh, "GLL DIALOG FORM TEST by (X)", WS_OVERLAPPEDWINDOW EditText "Test3" , iED, EDx, EDy, EDw, EDh, STYLE6 PushButton "PUSHBUTTON" , iPB, PBx, PBy, PBw, PBh, STYLE1 ListBox "" , iLB, LBx, LBy, LBw, LBh StatusCtrl "" , iSB, SBx, SBy, SBw, SBh, EndDialog ShowDialog # 1 ~SetFocus(DlgItem(1, 103)) EndProc Proc Notes() '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' NOTES ON A FEW WINDOW MESSAGE CONSTANT VALUES ' WM_NULL = 0x0000 ' WM_CREATE = 0x0001 ' WM_DESTROY = 0x0002 ' WM_MOVE = 0x0003 ' WM_SIZE = 0x0005 ' WM_ACTIVATE = 0x0006 ' WM_SETFOCUS = 0x0007 ' WM_KILLFOCUS = 0x0008 ' WM_ENABLE = 0x000A ' WM_SETREDRAW = 0x000B ' WM_SETTEXT = 0x000C ' WM_GETTEXT = 0x000D ' WM_GETTEXTLENGTH = 0x000E ' WM_PAINT = 0x000F ' WM_CLOSE = 0x0010 ' WM_QUIT = 0x0012 ' WM_ERASEBKGND = 0x0014 ' WM_SYSCOLORCHANGE = 0x0015 ' WM_SHOWWINDOW = 0x0018 ' WM_WININICHANGE = 0x001A ' WM_SETTINGCHANGE = 0x001A ' WM_DEVMODECHANGE = 0x001B ' WM_ACTIVATEAPP = 0x001C ' WM_FONTCHANGE = 0x001D ' WM_TIMECHANGE = 0x001E ' WM_CANCELMODE = 0x001F ' WM_SETCURSOR = 0x0020 ' WM_COMMAND = 0x0111 ' WM_MOUSEMOVE = 0x0200 ' and many more... ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' In GFA BASIC 32 for Windows, the `RetVal%` parameter is used to return an ' integer value from the callback to the caller, while the `ValidRet?` parameter ' is a boolean variable that controls whether the callback should proceed and ' if default processing should occur. ' ' In GFA BASIC 32 for Windows, the `RetVal%` parameter is an integer variable ' used to send a numerical result from the callback function back to the calling ' code. After the callback function is executed, the caller can examine the ' value of `RetVal%` to determine the outcome or status of the callback's ' execution. For instance, you might set `RetVal% = 0` to indicate successful ' execution and `RetVal% = 1` to signify an error or failure. ' ' On the other hand, the `ValidRet?` parameter is a boolean variable that ' influences the continuation of the callback's processing. When the callback ' is executed, it can adjust the value of `ValidRet?` to either `True` or ' `False`. If `ValidRet?` is set to `False`, it signals that the callback has ' taken care of processing the specific message and wants to prevent any further ' default processing by the system. Conversely, setting `ValidRet?` to `True` ' permits the callback's processing to proceed alongside the default handling. ° ° Here's an example of how these parameters could be used in GFA BASIC 32 for ' Windows: ' ' Sub Gfa_CB(hDlg%, Msg%, wParam%, lParam%, ByRef RetVal%, ByRef ValidRet?) ' Select Msg ' Case WM_SIZE ' // Handle resizing here ' <your code here> ' ' // Set RetVal% to indicate success ' RetVal% = 0 ' ' // Set ValidRet? to True to allow default processing ' ValidRet? = True ' End Select ' End Sub ' ' In this example, after managing the `WM_SIZE` message, `RetVal%` is assigned ' the value `0` to communicate the successful execution of the callback. ' Furthermore, the boolean `ValidRet?` is set to `True` to permit both the ' callback's processing and the default message handling to proceed. ' ' Remember, the precise utilization of these parameters hinges on your specific ' requirements and how your callback function is integrated into your GFA BASIC ' 32 for Windows application. They provide a means of conveying information ' back to the calling code and managing the flow of message processing. ' EndProc
Sub Gfa_CB(hDlg%, Msg%, wParam%, lParam%, ByRef RetVal%, ByRef ValidRet?) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Special conditions apply to coding for '.GLL's (GFA Editor Extension) files. ' This "built-in" to GFA-BASIC 32 for Windows GLL subroutine: Gfa_CB(), is the key ' to being able to respond to control events of a Dialog and any non-OCX controls ' that it contains. CB stands for CallBack, which implies that every time a ' Dialog or one of its controls generates a Window Message code (an event) then ' this Gfa_CB() subroutine will be called and 4 parameters will be passed to let ' the coder respond to or "handle" the messages. If you really know nothing of ' this then suffice to say it's the old way of doing things, but, in this case, ' it's the only way to get things done. Essentially a message contains 4 values ' that correspond to which Dialog generated the message, the type of message related ' to a specific control and sometimes, 'encoded values' related to the event. For example ' a mouse move event might be generated and be related to the dialog. The coordinates ' are encoded in the lParam (Long typed, 4 Byte variable). The coodinates could ' be decoded as follows: x = LoWord(lParam) for mouse x and y = HiWord(lParam) for mouse y. ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Here we are filtering the messages to process only those from the Dialog # 1. ' The hDlg passed parameter contains the "handle" of the form or dialog that ' generated the message. We compare it to the result of a function that gives us ' the handle of Dialog # 1: Dlg(1). If they match, we proceed to call a coder ' prepared procedure that will act on the 4 passed parameters: the message dataset. ' I will mention RetVal% and ValidRet% only to say that I don't yet know how to ' use them as they are not immediately causing a problem if I ignore them. ' See the Notes procedure in this code listing for ChatGPT's explanation. ' If (hDlg == Dlg(1)) Handle_Dlg_1(hDlg%, Msg%, wParam%, lParam%, RetVal%, ValidRet?) EndIf EndSub
Proc Handle_Dlg_1(hDlg%, Msg%, wParam%, lParam%, ByRef RetVal%, ByRef ValidRet?) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' So, if we've made it here, we are only dealing with messages that came from: ' Dialog # 1. We can now concentrate on the message codes which are conveniently ' standardized and stored in meaningfully named constants such as: WM_MOUSEMOVE, ' which stands for "Window Message Mouse Move". From inside a Select..Case ' routing command, we can branch off to specialized procedures to tackle each ' case individually. ' Select Msg Case WM_MOUSEMOVE E_WM_MOUSEMOVE(hDlg, Msg, wParam, lParam) Case WM_SIZE E_WM_SIZE(hDlg%, Msg%, wParam%, lParam%) EndSelect EndProc
Sub E_WM_MOUSEMOVE(hDlg, Msg, wParam, lParam) P_Post_Status_String(hDlg, Msg, wParam, lParam) EndSub
Sub E_WM_SIZE(hDlg%, Msg%, wParam%, lParam%) // E_ for Event... '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Handle a resize of the main window. Why? Because in this case, the statusbar ' is not being resized along with the window and we must resize it "manually". ' P_LB_Resize(hDlg%, Msg%, wParam%, lParam%) P_SB_Resize(hDlg%, Msg%, wParam%, lParam%) 'P_Post_Status_String(hDlg, Msg, wParam, lParam) EndSub
Proc P_LB_Resize(hDlg%, Msg%, wParam%, lParam%) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Based on the Dialog form or window's new size, adjust the control's size. ' Why? Because it is not being done automatically. ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Extract the new width and height from the lParam parameter ' Dim NewWidth As Long = LoWord(lParam) Dim NewHeight As Long = HiWord(lParam) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Resize the control using MoveWindow. ' Where, iLB is the control Id of the control. ' Dim hLB% = Dlg(hDlg, iLB) If (hLB <> 0) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Move / Resize the specified control using the specified: ' handle, x, y, w, h, flag... ' Dim LBw% = NewWidth - 20 Dim LBh% = NewHeight - PBy - PBh - SBh - 10 MoveWindow(hLB, LBx, LBy, LBw, LBh, 1) EndIf EndProc
Proc P_Post_Status_String(hDlg%, Msg%, wParam%, lParam%) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' This code is temporary and will serve to guide the coder to detect what ' "WM_" (window message) codes are flying around and what information is being ' passed along. ' Dim hLB% = DlgItem(1, iLB) Dim s$ = _ " hDL:" & Hex(hDlg, 8) & _ ", hLB:" & Hex(hLB, 8) & _ ", Msg:" & Hex(Msg, 8) & _ ", W:" & Hex(wParam, 8) & _ ", L:" & Hex(lParam, 8) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Add specified string to the specified list box via its handle... ' SendMessage hLB, LB_ADDSTRING, 0, s$ EndProc
Proc P_SB_Resize(hDlg%, Msg%, wParam%, lParam%) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Based on the Dialog form or window's new size, adjust the status bar's width. ' Why? Because it is not being done automatically. ' ' Extract the new width and height from the lParam parameter Dim NewWidth As Long = LoWord(lParam) Dim NewHeight As Long = HiWord(lParam) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Resize the StatusBar control using MoveWindow. ' Where, iSB is the control Id of the status bar. ' Dim hSB As Long = Dlg(hDlg, iSB) If hSB <> 0 Then '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Move / Rsize the specified control using the specified: ' handle, x, y, w, h, flag... ' MoveWindow(hSB, SBx, SBy, NewWidth, SBh, 1) EndIf EndProc
|
|