This is a Microsoft product indeed.
About its documentation : (Peek at answer #1)
Just my opinion: resource files approach is already satisfactory.
What about ui rendered in a web browser ? ( sort of CGI module / UIAdv module mix )
Printable View
This is a Microsoft product indeed.
About its documentation : (Peek at answer #1)
Just my opinion: resource files approach is already satisfactory.
What about ui rendered in a web browser ? ( sort of CGI module / UIAdv module mix )
Turns out my previous post with link (from the Visual Studio Marketplace) may have been trouble. The info seemed to make sense, but there was a download link in it which lead to a bad website. Don't click on it. I deleted that post and posted this instead:
Here is a better link from Code project:
https://www.codeproject.com/Articles/372559/DirectUI
If it is an inhouse UI library used by Microsoft in its own products, then it likely won't be well documented and might not be a good solution.
The basic concept seems to be to build a user interface on a graphic screen of sorts rather than use actual Windows controls. It would not be too difficult to build something similar using either low level GDI or GDI+ graphics or even using OpenGL.
The best way to start would be to build a Sprite engine into a Graphic window class. Sprites provide many of the basic features needed for a graphic UI engine.
Eros,
I am seriously considering creating an Open Source version of EZGUI 4.0 (not 5.0 Pro) and place it on GitHub. Would there be any interest in something like this for use with ThinBasic ?
The advantages of the EZGUI framework is that is is extremely easy to use and the commands do not require WIN32 API style coding. The code layout is much easier to work with than the Powerbasic like DDT style coding.
You can download a zip with a few simple EZGUI apps (and runtime) to see how they are coded and run (EXE's already compiled).
Attachment 10116
Here is an example of an EZGUI app is laid out:
The idea is to allow either the binary (DLL) to be used (write wrappers for it) or to use the Source code and port it or fork it to any project.Code:#COMPILE EXE
#DIM ALL
' --------------------
#INCLUDE "..\includes\ezgui40.inc"
' --------------------
' *************************************************************************************
' Application Constants and Declares
' *************************************************************************************
%FORM1_LABEL1 = 100
%FORM1_HScrollBar1 = 105
%FORM1_LABEL2 = 110
' ------------------------------------------------
DECLARE SUB FORM1_HScrollBar1_Click()
' --------------------
#INCLUDE "..\includes\ezwmain.inc" ' EZGUI Include file for WinMain
' --------------------
SUB EZ_Main(VerNum&) EXPORT
EZ_LoadPatternLib "", ""
EZ_Color 0,-56
EZ_Form "FORM1", "", "Select Colors", 0, 0, 48, 18, "C"
END SUB
' -------------------------------------------------------------------------------------
SUB EZ_DesignWindow(FormName$) EXPORT
SELECT CASE FormName$
CASE "FORM1"
EZ_Color 0, 0
EZ_UseFont -1
EZ_UseFont 4
EZ_Label %FORM1_LABEL1, 1, 1, 46, 10, "", "CS"
' --------------------------------
EZ_Color -1,-1
EZ_UseFont 4
EZ_HScroll %FORM1_HScrollBar1, 2, 12, 44, 1.5, ""
EZ_SetHScroll "FORM1", %FORM1_HScrollBar1, -57, 36, 0, 5
' --------------------------------
EZ_Color 15, 1
EZ_DefFont 10, "Tahoma", 16, "BV"
EZ_UseFont 10
EZ_Label %FORM1_LABEL2, 2, 15, 45, 2, "Move Slider to change colors", "CI"
' --------------------------------
CASE ELSE
END SELECT
END SUB
' -------------------------------------------------------------------------------------
SUB EZ_Events(FormName$, CID&, CMsg&, CVal&, Cancel&) EXPORT
SELECT CASE FormName$
CASE "FORM1"
SELECT CASE CID&
CASE %EZ_Window
IF CMsg&=%EZ_Close THEN
END IF
CASE %FORM1_HScrollBar1
IF CMsg&=%EZ_Change THEN
IF CVal&<=31 THEN
EZ_SetColor "FORM1", %FORM1_LABEL1, 0, CVal&
EZ_SetText "Form1", 0, "Current Color Number is "+STR$(CVal&)
END IF
END IF
CASE ELSE
END SELECT
CASE ELSE
END SELECT
END SUB
This is not a "done deal" yet, but simply in the concept stage right now.
Any thoughts ?
The advantages of the EZGUI framework is that it has its own Event engine with much easier to use event messaging. One can actually process every event for the app in one routine (EZ_Events) or break it up (parse out each form or control in EZ_Events and call a routine for each).
For example like a Scrollbar is very easy. You get the %EZ_Change event when the scrollbar position changes and the new position is passed in the event in the CVal& parameter (all events get passed five parameters, (1) Form name, (2) Control ID, (3) Event constant (4) CVal& is unique to each event (5) Cancel& parameter to cancel default processing for some events).
New users using this framework can be up and running writing apps in a few hours.
Ciao Chris,
it is not up to me if there is interest in EZGui, I just develop thinasic.
It is up to programmers using thinBasic to take advantage of EXGui and to you in promoting EZGui and assist users.
From my side, what I can do is to see if EZGui can be used (as easy as possible) inside thinBasic scripts.
The rest is in the hands of programmers.
If you can attach include files "ezgui40.inc" and "ezwmain.inc" in the zip I can make tests to see if thinBasic can parse them at runtime.
As far as I see from attached .BAS examples it seems just a matter of calling standard functions and passing parameters so I do not see much problems but till I do not test it I cannot say all is compatible with thinBasic engine parser.
Today I will be out all the day but if you attach include files I can test during the week-end report results.
Ciao
Eros
I like very much the clean and supereasy syntax as Textbox has now.
Like
Only half a line! Which was before a bunch of Handles, IDs and additional variables asCode:1. !!!
TextOut.Text &= TextIn.Text
for the same result that intransparent mind-twisting many words writing verbose kill-a lot-of-timeCode:2. ???
String sInput
Control Get Text CBHNDL, %tbxIn to sInput
Control Append Text CBHNDL, %tbxOut , sInput
syntax. Just look once again at the fist line. It says it all. Straightforward. No explanation needed.
Only a tiny problem with that, seems there is a problem with backward compatibility - the old syntax
does not work correct. Paste some text from clipboard into a textbox and request Control Get Text
- stays empty.
The Callback Function TextIn_OnChange() is using old syntax currently. Select and cut or comment the marked lines if you want to use the new syntax.
The script is just a template to pretend some console-like In & Output with 2 Textboxes. The upper box
should be something as STDOUT, the lower one STDIN - accepts input.
Code:' thinBasic UI-script-Template TextIn & TextOut
#Region "Preprocessing"
'---------------------------------------------------------------
Uses "UI", "INI", "OS"
'---------------------------------------------------------------
#EndRegion
'##############################################################################################
#Region "Equatification"
'---------------------------------------------------------------
begin Const
$APP_Title = "NewScript_Untitled" ' use chars taht are valid in filenames
$Prompt = "Ready >"
%LenPrompt = lenf($Prompt) ' do not recalculate, it will not change
' FONTS: use 3: %monospaced, %regularFont + %HeaderFont
' prepared to use an non-OOBE-font (OOBE=Out Of the Box-Experience)
' so if a fonts was not shipped with windows not every user has it.
' therefore check and provide a fallback-font if we don't ship the
' font with this app.
' replace "PT MONO" with your favorite monospaced font if you don't
' have it on your system - or fallback to Courier New
%monoSpaced = iif$( instr(1, ucase$(Font_List), "PT MONO"),
font_new("PT Mono",10), Font_New("Courier New",10) )
' header-font for captions headers, menus
%HeaderFont = iif$( instr(1, Ucase$(Font_List), "OPENDYSLEXIC"),
font_new("OpenDyslexic",12), Font_new("Tahoma",12 ) )
' for usual text, information, description
%regularFont = iif$( instr(1, Ucase$(Font_List), "SERGOE UI"),
font_new("Sergoe UI",10), Font_new("MS Sans Serif",10 ) )
%hDlgMain ' slot for window-handle of dialog main
%hTextOut ' require handle to send text from another
%Not_CaseSensitive = 0
%thisProcess = OS_GetCurrentProcessId ' process to get displayed here
' %EvalScriptName = app_scriptpath & "QuestionToCore.tBasic"
' %EvalScriptHeader = Load_File(app_scriptpath & "QuestionTemplate.tBasicI")
end Const
begin ControlID
%tbX_OUT 'Output
%tbx_IN 'Input
%btn_Exit 'Stop
' timer to invoke ReDraw after user is
' done with the size-adjustmments to avoid
' repeatedly refresh while still sizing
%delayToRefresh
'--------------- MenuBar-popups
'--------------- Menuitems
end ControlID
'---------------------------------------------------------------
#EndRegion
'##############################################################################################sub CreateMainWindow( byref hDlg as Dword,
#Region "Global Variables"
'---------------------------------------------------------------
global Script2Eval as string
'---------------------------------------------------------------
#EndRegion
'##############################################################################################sub CreateMainWindow( byref hDlg as Dword,
' >> setup procedure of the applications main window <<
Sub CreateMainWindow( byref hDlg as dword,
optional byval Title$ as string,
byval hParent AS DWORD )
'------------------------------------------------------------------
' -- set initial window position & size for first execution
long x = -1
long y = -1
long w = 360
long h = 270
long lStyle = %WS_CLIPCHILDREN | %WS_CLIPSIBLINGS | %WS_DLGFRAME |
%WS_CAPTION | %WS_SYSMENU | %WS_OVERLAPPEDWINDOW
Long lExStyle = %WS_EX_TOOLWINDOW
boolean SkipIniSettings ' = True ' override Inifile temporary
' --------------------------------------------------------------------
long cW, cH
Desktop get client to cW, cH
' -- if positions not in range then use centered
if not between(X, 0, cW-W) then x = minmax(cW/2 - w/2, 0, cW - W)
if not between(Y, 0, cH-H) then y = minmax(cH/2 - h/2, 0, cH - H)
if Not SkipIniSettings Then
' -- if no caption passed use the app-title as windoow-caption
if Title$ = "" then Title$ = $App_Title
' -- check the inifile for the last settings
x = val( ini_getkey(App_inifile, "DlgMain", "X", str$(X)))
y = val( ini_getkey(App_inifile, "DlgMain", "Y", str$(Y)))
w = val( ini_getkey(App_inifile, "DlgMain", "W", str$(W)))
h = val( ini_getkey(App_inifile, "DlgMain", "H", str$(H)))
EndIf
' -- apply all settings to new created dialog
Dialog New Pixels, Name DlgMain, hParent, Title$,
x, y, w, h,
lStyle, lExstyle To hDlg
dialog get client hDlg to cW, cH
' -- Dialog ready to take controls now
' use monospaced fonts for a console alike impression at TextIn & TextOut
SendMessage(hDlg, %WM_FONTCHANGE, %monospaced, 0)
local hCtrl as dword at varptr(%hTextOut)
hCtrl = Control Add Textbox, Name TextOut, hDlg, %tbx_Out, "", 5, 5, cW-10, cH - 105,
%ES_MULTILINE | %ES_AUTOHSCROLL | %ES_AUTOVSCROLL | %WS_VSCROLL | %ES_ReadOnly,
%WS_EX_StaticEDGE | %ws_ex_left
Control set font hDlg, %tbx_OUT, %monospaced
control set Resize hDlg, %tBX_Out, 1, 1, 1, 1
Control Add Textbox, Name TextIn, hDlg, %tbx_In, $Prompt, 5, cH-95, cW-10, 60,
%WS_Tabstop | %ES_MULTILINE | %ES_AUTOHSCROLL | %ES_AUTOVSCROLL | %WS_VSCROLL | %Es_WantReturn,
%WS_EX_CLIENTEDGE | %ws_ex_left
control set Resize hDlg, %tBX_IN, 1, 1, 0, 1
Control Set Font hDlg, %tbx_IN, %monospaced
Control set Focus hDlg, %tbx_IN
control Append text hDlg, %tbx_IN, $Spc ' to prevent selection of $Prompt
' change font to HeaderFont for all other controls
SendMessage(hDlg, %WM_FONTCHANGE, %HeaderFont, 0)
control add button, Name btnExit, hDlg, %btn_Exit, "Exit", cW * 0.667, ch-32, cW * 0.333-5, 30, %BS_DEFAULT
Control set Font hDlg, %btn_Exit, %HeaderFont
control set Resize hDlg, %btn_Exit, 0, 1, 0, 1
'----------------------------------------------------------------
End sub
'###############################################################
' >> check the input for contained message <<
Function IsPossible(Byref sInPut As String) As Boolean
Long lSpace
Number ExecutionTime, ExecDuration
'---------------------------------------------------------------
if startswith(sInput, "cmd", %Not_CaseSensitive) then
TextOut.Text &= Shell_CaptureInput(sInput,,,5000) & CRLF
elseif startswith(sInput, "Run ", %Not_CaseSensitive) then
sInput = Remain$(sInput, "Run ", %Not_CaseSensitive))
if Any ( Endswith(sInput, ".exe", %Not_CaseSensitive),
Endswith(sInput, ".msi", %Not_CaseSensitive),
Endswith(sInput, ".mmc", %Not_CaseSensitive),
Endswith(sInput, ".lnk", %Not_CaseSensitive),
Endswith(sInput, ".symlnk", %Not_CaseSensitive) ) Then
' not passing parameters
TextOut.Text &= "Executing " & sInput & "..." & CRLF
shell(sInput,,true)
' elseIf startswith(sInput, "RunAs ", %Not_CaseSensitive) then
'[todo] run as AdMin
endif
else
if Instr(2, sInput Any " /-+:=" & $DQ ) > 0 then
' some parametes obviouslay, append a file where
' to put the results. Make sure it contains the right message if failure...
Save_File(App_Scriptpath & "returned.txt", sInput & " did not return any usable result" & crlf)
sInput &= " > " & App_Scriptpath & "returned.txt"
Shell(sInput,"")
TextOut.Text &= Load_File(App_Scriptpath & "returned.txt")
endif
endif
sTextOut.Text &= crlf
'---------------------------------------------------------------
End Function
'####################################################################################################
#Region "Callback Functions" '### Callback Functions ### Callback Functions### Callback Functions ###
'####################################################################################################
' >> Refresh of the dialog is invoked after resizing by a timer <<
CallBack Function DlgMain_OnTimer() As Long
long W,H
'-------------------------------------------------------------------
if cbctl = %delayToRefresh then
dialog get size cbhndl to w, h
dialog set size cbhndl, w + 1, h ' tiny movements horizontal
dialog set size cbhndl, w, h + 1 ' & vertical to make the
dialog set size cbhndl, w, h ' controls looking good again
dialog Redraw cbhndl
dialog kill timer cbhndl, cbctl
Endif
function=true ' reply the callback - else it will not
' bother to send messages. if no reply
' it will not waste any more energy to
' call on functions that seem not to exist
' nor such that seem to have no body
'-------------------------------------------------------------------'-------------------------------------------------------------------
End Function
'##############################################################################################
' >> after dialog got resized its time to redraw all objects <<
CallBack Function DlgMain_OnSizing() As Long
'-------------------------------------------------------------------
Dialog set Timer %hDlgMain, %delayToRefresh, 200
' use of a timer to redraw the window content after resizing
' the window to prevent the content from flickering
function = true
'-------------------------------------------------------------------
End Function
'##############################################################################################
CallBack Function DlgMain_OnDestroy() As Long
'-------------------------------------------------------------------
Long x, y
'-------------------------------------------------------------------
' -- final save of settings
dialog Get loc %hDlgMain to x,y
ini_setkey(App_inifile, "DlgMain", "X", str$(X))
ini_Setkey(App_inifile, "DlgMain", "Y", str$(Y))
dialog get size %hDlgMain to x, y
ini_Setkey(App_inifile, "DlgMain", "W", str$(X))
ini_Setkey(App_inifile, "DlgMain", "H", str$(Y))
'-------------------------------------------------------------------
End Function
'##############################################################################################
CallBack Function TextIn_OnChange() As Long
String sInput
'-------------------------------------------------------------------
'--- SELECTION START HERE --- SELECTION START HERE --- SELECTION START HERE ---
' V
' V select this part and cut it
' V
' V
' V
'[todo] check this out: old syntax not functioning
if all(cbmsg=%WM_command, getasynckeystate(%VK_Return)) then
' V
' V
' V
control get text %hDlgMain, %tbx_IN to sInput
if startswith(sInput, $Prompt) Then
' V
sInput= trimfull$( Remove$(sInput, $Prompt) )
control_appendtext( %hDlgMain, %tbx_OUT, sInput & crlf )
' V
control set Text %hDlgMain, %tbx_IN, $Prompt
' V
control append text %hDlgMain, %tbx_IN, $SPC
endif
endif
' V
' V
' V
if GetAsyncKeyState(-1) then nop 'clear it...
function = true
end Function
CallBack Function ERASE_THIS_LINE(SELECTTION_Start_At_MARKED_LINE_244,
GO_DOWN_TO_SELECT_UNTIL_LINE_270,
THEN_DELETE_SELECTION_AND_RUN_AGAIN) As Long
' V
' V
' V
' --- SELECTION END HERE --- SELECTION END HERE --- SELECTION END HERE ---
if GetAsyncKeyState(%VK_RETURN) then
sInput = trimfull$(remove$(TextIn.Text, crlf))
TextIn.Text = ""
textOut.Text = textOut.Text & sInput & CRLF
select case lCase$(sInput)
case "cls", "clr"
TextOut.Text = ""
case "exit", "stop", "quit"
dialog end %hDlgMain
case Else
if Not IsPossible(sInput) then
textOut.Text = textOut.Text & "unable to process " & $DQ & sInput & $DQ & crlf
EndIf
end select
endif
' request to clear (-1) and take the result from stack
sInput = mkl$(GetAsyncKeyState(-1))
function = true ' reply to continue receiving messages
'-------------------------------------------------------------------
end Function
'##############################################################################################
CallBack Function btnExit.onClick() As Long
'----------------------------------------------------------------------------------------------
dialog end %hDlgMain
function = true
end Function
'----------------------------------------------------------------------------------------------
#EndRegion
'##############################################################################################
'### TBMain() ### TBMain() ### TBMain() ### TBMain() ### TBMain() ### TBMain() ### TBMain() ###
'###############################################################################################
Function TBMain() As Long
'---------------------------------------------------------------------
CreateMainWindow(%hDlgMain) ' call to create the main dialog
dialog set Minsize %hDlgMain, 160, 120 ' apply the minimum size
DIALOg show Modeless %hDlgMain ' use automatic Callback
if HiResTimer_Init then nop ' will use HiResTimer sometimes
' -- entering the
' MAIN LOOP
' -- >>>
repeat
DoEvents
until NOT isWindow( %hDlgMain )
' -- hurry, the rats are leaving the ship!
'---------------------------------------------------------------------
End Function
'#####################################################################################
'### EOF ### EOF ### EOF ### EOF ### EOF ### EOF ### EOF ### EOF ### EOF ### EOF ###
'#####################################################################################
This script (ok i will change it a bit) gets created if i rightclick somewhere and
the context-menu shells, i select "NEW..." "thinbasic.Script.File" - and there it is. I also can choose a thinbasic.consolescript.file
If you want the fonts - check in my downloads of thinAir-Themes-thread
We write
the perfect idea (so simple you will kick yourself for not thinking of that)Code:{Control|Dialog} Add {aWindowsObject}, Name thisNameICanChoose, ...
type t_MyDialog
hWin as Dword
hParent as Dword
End Type
Global thisNameICanChoose as tDialog
use the UDT-VariableName to connect the both! Index? No more problem.
Find ME for inside a Callback? What for... Call my name!
Only 1 thing:
Reverse Develop syntax for Callback-function names to accept ONLY UNDERSCORE but not period/dot.
The DOT/PERIOD says "HEY I AM MEMBER OF AN UDT"
the underscore just connects words...
If No dot in the functions name it will be no confusion when parsing it.
When assigning the NAME to a control and the name is any Variable(except dynamic string) or an UDT then
UI can easily grab the varptr and keep it to define ME.
Just that one more thought: To make sure and foolproof the variable must not be redimensioned nor relocated.
So the Varptr that UI keeps in mind will stay the same for duration of execution.
One idea: Make the UDT-MAIN-Variable unchangeable as Equates are. An predefined UDT with basic subelements
of 20 Bytes (reserved for hWin, hParent, ControlID...). The USER MUST CREATE AN UDT that extends this one then.
The other Idea: UI will move the memory and store the udt variable at another place and connect the function-pointers only. The variables subelements are no accessible directly then so they all must be wrapped with a function
before the call to control/dialog add.
That makes it automatic that the controls names subelements become kind of private.
Third idea: a combination of both.
UI should provide
a basic Dialog-UDT -one for all dialogs
a basic udt for all visible Controls from button up to treeview and webbrowser
a basic UDT for every invisible control (that are not really controls) but objects as TIMERS, IMAGELISTS etc.
and one predefined UDT that can node siblings and children that can be used for menuitems, treeviewItems and tabcontrolpage. Yes make a tabControl inside the tab of a tabcontrol.... :D
Thanks ReneMiner for this nice program, i haven't expected that we can use a Text Box as if it is something like a command prompt. but when we delete the Ready > it behaves like a normal Text Box .the code is very long but i guess it is part of a bigger code. the function Shell_CaptureInput seems new, i haven't found it in TB examples except in the help file . i will not be able to understand it now but it is surely a jewel for a future usage.
Hi all,
I know this is an old thread. But I would like to tell you something. I am writting a GUI library in ThinBasic. Since, thinBasic UI is not supporting unicode, I wrote my own with full unicode support. Here is the sampe code.
Please see the attachment for the resulted window.Code:
Uses "UI"
#include ".\ThinUi\*" '// I put all my library modules in this folder for easiness
Dim win As tWindow
with Win
.SetText("Thin Window")
.SetPosition(400, 50)
'.SetSize(650, 300)
'.OnMouseDown = "Win_MouseDown"
'.MaximizeBox = false
'.SetGradientBackColor(0xF17fBB, 0xddff23)
End With
win.MakeWindow() '// Here is the actual window creation happens.
Dim btn As tButton(win)
with btn
.setPosition(300, 50)
.SetSize(180, 50)
.SetFont("Tahoma", 12)
.SetText("Gradient Button")
.OnClick = "B1_Click"
.SetGradient(0x66ccff, 0xddff23)
.MakeButton()
End With
Dim btn2 As tButton(win)
with btn2
.setPosition(50, 50)
.SetSize(150, 40)
.SetFont("Calibri", 12)
.SetText("Color Btn")
.OnClick = "B2_click"
.SetForeColor(0x0052cc)
.SetBackColor(0x99ff66)
.MakeButton()
End With
Dim btn3 As tButton(win)
with btn3
.setPosition(50, 150)
.SetSize(180, 50)
.SetFont("Colonna MT", 15)
.SetText("Normal Button")
.OnClick = "Btn2_Onclick"
.SetForeColor(0xff0000)
.MakeButton()
End With
win.Display() '// Now we can show the window.
'// Here is the button click event handler.
Function B1_Click(tb As tButton, e As tEventArgs)
MsgBoxW("Hi from thinBasic")
End Function
Till now, I have completed Window module & button module. I am gradually developing other controls.
Hi,
it looks fantastic!
Petr