ProGUI V3 Alpha Sneak Peek!
Re: ProGUI V3 Alpha Sneak Peek!
The rendering of the Richedit is diverted directly onto a DirectX 11 Direct2D bitmap though so it can still have alpha transparency and be composited with alpha masking just not it's background if you know what I mean as the control has no alpha channel (GDI)
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
The Caret is GPU rendered though
(Well it's all GPU rendered just the Direct2D / GDI interop bitmap is CPU backed-up/mirrored I think)


ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
Hi guys I thought I'd share an example source code of the API in it's current form (from one of my test examples):
Code: Select all
Global NewMap layoutmap.s()
IncludeFile "ProGUI.pbi"
CompilerIf #PB_Compiler_Backend = #PB_Backend_C
Debug "Using C backend"
CompilerEndIf
driver = #PG_RenderDirect2D
;driver = #PG_RenderVector
;driver = #PG_RenderCairo
StartProGUI(driver)
; Global timg1 = LoadImg("Icons\bg_96dpi.jpg", 0)
Global timg1 = LoadImg("Icons\bg_96dpi.png", 0)
;Global backgroundMask = LoadImg("Icons\backgroundMask.png", 0)
Global backBrush = CreateImgBrush(timg1)
BrushSetExtendMode(backBrush, #PG_Brush_ExtendMode_Repeat, #PG_Brush_ExtendMode_Repeat)
;BrushSetScale(backBrush, 1, 1, 150, 150)
;BrushSetScale(backBrush, 1.5, 1.5, 200, 0)
;BrushSetPosition(backBrush, 200, 0)
;BrushSetRotation(backBrush, 45, 200, 0)
;FreeImg(timg1)
Global timg2 = LoadImg("Icons\boingball.png", 0)
; Global timg3 = ImgGrab(timg2, 0, 0, 40, 40)
Global testimg = CreateImg(200, 200, RGBA(255, 0, 255, 255))
BeginDraw(OutputImg(testimg))
DrawBox(20, 20, 50, 50, RGB(255, 255, 0), 1)
EndDraw()
Global tbordermask = LoadImg("Icons\border_new_mask2.png", 0)
Global tborderimg = LoadImg("Icons\border_new2.png", 0)
rc.RECT
rc\left = 20
rc\right = 70
rc\top = 20
rc\bottom = 70
; Global tborderimg = LoadImg("Icons\border29_.png", 0)
; rc.RECT
; rc\left = 50
; rc\right = 210
; rc\top = 50
; rc\bottom = 210
Global tborder = CreateBorder(tborderimg, tbordermask, rc)
;Global ttext = CreateText("Hello this is a test!", "Verdana", 30)
Global ttext = CreateText("ABCD abcd 1234 ASbd!Qgjq - default menu font - ", "Verdana", 12)
Procedure draw(*window.Window, EventType, *eventData.PG_EventData)
Static count.f
; DrawClear(RGB(240, 240, 240), 1)
;
; DrawBoxFill(0, 0, WindowGetWidth(*window), WindowGetHeight(*window), backBrush)
DrawClear(0, 0)
;DrawClear(RGB(240, 240, 240), 1)
BeginLayer(0, 0, WindowGetWidth(*window), WindowGetHeight(*window), 1, 0, tborder)
BrushSetOpacity(backBrush, 0.7)
DrawBoxFill(0, 0, WindowGetWidth(*window), WindowGetHeight(*window), backBrush)
EndProcedure
Procedure drawForeground(*window.Window, EventType, *eventData.PG_EventData)
;DrawBox(0, 0, *eventData\width, *eventData\height, RGB(240, 0, 0), 0.8)
EndLayer()
EndProcedure
Procedure drawTestWidget(*widget.Widget, EventType, *eventData.PG_EventData)
DrawBox(0, 0, *eventData\width, *eventData\height, RGB(0, 200, 0), 0.5)
EndProcedure
Procedure CreateTestWidget()
*widget = CreateWidget(0, 0, 0, 0)
AddEventHandler(*widget, #PG_Event_Draw, @drawTestWidget())
;AddEventHandler(*widget, #PG_Event_DrawForeground, @drawForeground())
layout = CreateLayout()
LayoutSetType(layout, #PG_Layout_Type_Flex)
LayoutSetProperty(layout, #PG_Flex_Direction, #PG_Flex_Direction_Row)
LayoutSetProperty(layout, #PG_Flex_Wrap, #PG_Flex_Wrap_Enabled)
WidgetSetLayout(*widget, layout)
ProcedureReturn *widget
EndProcedure
Procedure drawTestWidget2(*widget.Widget, EventType, *eventData.PG_EventData)
DrawBox(0, 0, *eventData\width, *eventData\height, RGB(200, 200, 0), 0.5)
EndProcedure
Procedure drawTestWidget3(*widget.Widget, EventType, *eventData.PG_EventData)
DrawBox(0, 0, *eventData\width, *eventData\height, RGB(200, 200, 0), 0.5)
EndProcedure
Procedure drawTestWidget4(*widget.Widget, EventType, *eventData.PG_EventData)
DrawBox(0, 0, *eventData\width, *eventData\height, RGB(0, 200, 200), 0.5)
EndProcedure
Procedure CreateTestWidget2()
*widget = CreateWidget(0, 0, 0, 0)
AddEventHandler(*widget, #PG_Event_Draw, @drawTestWidget2())
layout = CreateLayout()
LayoutSetType(layout, #PG_Layout_Type_Flex)
LayoutSetProperty(layout, #PG_Flex_Direction, #PG_Flex_Direction_Column)
LayoutSetProperty(layout, #PG_Flex_Wrap, #PG_Flex_Wrap_Enabled)
WidgetSetLayout(*widget, layout)
ProcedureReturn *widget
EndProcedure
Procedure CreateTestWidget3()
*widget = CreateWidget(0, 0, 0, 0)
AddEventHandler(*widget, #PG_Event_Draw, @drawTestWidget3())
layout = CreateLayout()
LayoutSetType(layout, #PG_Layout_Type_Grid)
LayoutSetProperty(layout, #PG_Grid_Flow, #PG_Grid_Flow_RowDense)
WidgetSetLayout(*widget, layout)
ProcedureReturn *widget
EndProcedure
Procedure CreateTestWidget4()
*widget = CreateWidget(0, 0, 0, 0)
AddEventHandler(*widget, #PG_Event_Draw, @drawTestWidget4())
layout = CreateLayout()
LayoutSetType(layout, #PG_Layout_Type_Grid)
LayoutSetProperty(layout, #PG_Grid_Flow, #PG_Grid_Flow_RowDense)
WidgetSetLayout(*widget, layout)
ProcedureReturn *widget
EndProcedure
Procedure WindowMouseLeftButtonDownEventHandler(Window, EventType, *eventData.PG_EventData, *userData)
Debug "WindowMouseLeftButtonDownEventHandler: " + Str(Window) + " mouseX: " + Str(*eventData\x) + " mouseY: " + Str(*eventData\y)
WindowSetMouseCapture(Window)
EndProcedure
Procedure WindowMouseLeftButtonUpEventHandler(Window, EventType, *eventData.PG_EventData, *userData)
Debug "WindowMouseLeftButtonUpEventHandler: " + Str(Window) + " mouseX: " + Str(*eventData\x) + " mouseY: " + Str(*eventData\y)
WindowReleaseMouseCapture()
EndProcedure
Procedure WindowMouseMoveEventHandler(Window, EventType, *eventData.PG_EventData, *userData)
Debug "WindowMouseMoveEventHandler: " + Str(Window) + " mouseX: " + Str(*eventData\x) + " mouseY: " + Str(*eventData\y)
EndProcedure
Procedure WindowMouseEnterEventHandler(Window, EventType, *eventData.PG_EventData, *userData)
Debug "WindowMouseEnterEventHandler: " + Str(Window)
EndProcedure
Procedure WindowMouseLeaveEventHandler(Window, EventType, *eventData.PG_EventData, *userData)
Debug "WindowMouseLeaveEventHandler: " + Str(Window)
EndProcedure
Procedure WidgetMouseLeftButtonDownEventHandler(*Widget.Widget, EventType, *eventData.PG_EventData, *userData)
Debug "WidgetMouseLeftButtonDownEventHandler: " + Str(Widget) + " mouseX: " + Str(*eventData\x) + " mouseY: " + Str(*eventData\y)
EndProcedure
Procedure WidgetMouseLeftButtonUpEventHandler(*Widget.Widget, EventType, *eventData.PG_EventData, *userData)
Debug "WidgetMouseLeftButtonUpEventHandler: " + Str(Widget) + " mouseX: " + Str(*eventData\x) + " mouseY: " + Str(*eventData\y)
EndProcedure
Procedure WidgetMouseMoveEventHandler(Widget, EventType, *eventData.PG_EventData, *userData)
Debug "WidgetMouseMoveEventHandler: " + Str(Widget) + " mouseX: " + Str(*eventData\x) + " mouseY: " + Str(*eventData\y)
EndProcedure
Procedure WidgetMouseEnterEventHandler(Widget, EventType, *eventData.PG_EventData, *userData)
Debug "WidgetMouseEnterEventHandler: " + Str(Widget)
EndProcedure
Procedure WidgetMouseLeaveEventHandler(Widget, EventType, *eventData.PG_EventData, *userData)
Debug "WidgetMouseLeaveEventHandler: " + Str(Widget)
EndProcedure
Structure TestWidget
*window.Window
isClick.i
isOver.i
EndStructure
Procedure TestWidgetEventHandler(Widget, EventType, *eventData.PG_EventData, *userData)
Select EventType
Case #PG_Event_Draw
DrawBox(0, 0, *eventData\width, *eventData\height, RGB(0, 50, 100), 1)
*testWidget.TestWidget = *userData
If *testWidget\isClick
DrawBox(0, 0, *eventData\width, *eventData\height, RGB(255, 0, 0), 0.8)
EndIf
If *testWidget\isOver
DrawBox(0, 0, *eventData\width, *eventData\height, RGB(200, 200, 255), 0.3)
EndIf
Case #PG_Event_MouseLeftButtonDown
*testWidget.TestWidget = *userData
*testWidget\isClick = #True
WidgetSetMouseCapture(Widget)
WidgetRedraw(Widget)
Case #PG_Event_MouseLeftButtonUp
*testWidget.TestWidget = *userData
*testWidget\isClick = #False
WidgetReleaseMouseCapture()
WidgetRedraw(Widget)
Case #PG_Event_MouseEnter
*testWidget.TestWidget = *userData
*testWidget\isOver = #True
Debug "Enter"
WidgetRedraw(Widget)
Case #PG_Event_MouseLeave
*testWidget.TestWidget = *userData
*testWidget\isOver = #False
Debug "Leave"
WidgetRedraw(Widget)
Case #PG_Event_MouseMove
Debug "move x: " + Str(*eventData\x) + " y: " + Str(*eventData\y)
EndSelect
EndProcedure
Procedure CreateTestWidget5(*window)
*widget = CreateWidget(0, 0, 0, 0)
*testWidget.TestWidget = AllocateStructure(TestWidget)
*testWidget\window = *window
AddEventHandler(*widget, #PG_Event_Draw, @TestWidgetEventHandler(), *testWidget)
AddEventHandler(*widget, #PG_Event_MouseLeftButtonDown, @TestWidgetEventHandler(), *testWidget)
AddEventHandler(*widget, #PG_Event_MouseLeftButtonUp, @TestWidgetEventHandler(), *testWidget)
AddEventHandler(*widget, #PG_Event_MouseEnter, @TestWidgetEventHandler(), *testWidget)
AddEventHandler(*widget, #PG_Event_MouseLeave, @TestWidgetEventHandler(), *testWidget)
AddEventHandler(*widget, #PG_Event_MouseMove, @TestWidgetEventHandler(), *testWidget)
ProcedureReturn *widget
EndProcedure
Procedure WindowAnimateEventHandler(Window, EventType, *eventData.PG_EventData, *userData)
Static brushX.d, brushY.d, brushZoom.d = 1, brushZoomSpeed.d, brushZoomFlip
brushY + 1
max.d = 0.01
speed.d = 0.0001
If brushZoomFlip
brushZoomSpeed - speed
If brushZoomSpeed < -max
brushZoomFlip = #False
EndIf
Else
brushZoomSpeed + speed
If brushZoomSpeed > max
brushZoomFlip = #True
EndIf
EndIf
brushZoom + brushZoomSpeed
BrushSetScale(backBrush, brushZoom, brushZoom, WindowGetWidth(Window)/2, WindowGetHeight(Window)/2)
BrushSetPosition(backBrush, brushX, brushY)
WindowRedraw(Window)
EndProcedure
Structure Sprite
x.d
y.d
width.d
height.d
direction.i
EndStructure
Procedure drawTestWidgetAnim(*widget.Widget, EventType, *eventData.PG_EventData, *sprite.Sprite)
DrawBox(0, 0, *eventData\width, *eventData\height, RGB(0, 0, 200), 0.5)
DrawBox(*sprite\x, *sprite\y, *sprite\width, *sprite\height, RGB(200, 0, 0), 0.8)
EndProcedure
Procedure TestWidgetEventHandlerAnim(*widget.Widget, EventType, *eventData.PG_EventData, *sprite.Sprite)
Select EventType
Case #PG_Event_Animate
Select *eventData\state
Case #PG_Event_Animate_Update
If *sprite\direction = 0
*sprite\x + 1
Else
*sprite\x - 1
EndIf
If *sprite\x < 0
*sprite\x = 0
*sprite\direction = 0
ElseIf *sprite\x + *sprite\width > 200
*sprite\x = 200 - *sprite\width
*sprite\direction = 1
EndIf
WidgetRedraw(*widget)
EndSelect
EndSelect
EndProcedure
Procedure CreateTestWidgetAnim(x, y, width, height)
*widget = CreateWidget(x, y, width, height)
*sprite.Sprite = AllocateStructure(Sprite)
*sprite\width = 20
*sprite\height = 20
*sprite\y = 80
AddEventHandler(*widget, #PG_Event_Draw, @drawTestWidgetAnim(), *sprite)
AddEventHandler(*widget, #PG_Event_Animate, @TestWidgetEventHandlerAnim(), *sprite)
anim = StartAnimation(*widget, "testAnim2")
; layout = CreateLayout()
; LayoutSetType(layout, #PG_Layout_Type_Flex)
; LayoutSetProperty(layout, #PG_Flex_Direction, #PG_Flex_Direction_Row)
; LayoutSetProperty(layout, #PG_Flex_Wrap, #PG_Flex_Wrap_Enabled)
; WidgetSetLayout(*widget, layout)
ProcedureReturn *widget
EndProcedure
OpenConsole()
;*window.Window = CreateWindow(0, 0, 800, 600, "Test", #PG_Window_MinimizeWidget | #PG_Window_MaximizeWidget | #PG_Window_Sizeable)
*window.Window = CreateWindow(0, 0, 800, 600, "Test", #PG_Window_BorderLess | #PG_Window_Sizeable, 0)
; AddEventHandler(*window, #PG_Event_MouseEnter, @WindowMouseEnterEventHandler())
; AddEventHandler(*window, #PG_Event_MouseLeave, @WindowMouseLeaveEventHandler())
; AddEventHandler(*window, #PG_Event_MouseMove, @WindowMouseMoveEventHandler())
; AddEventHandler(*window, #PG_Event_MouseLeftButtonDown, @WindowMouseLeftButtonDownEventHandler())
; AddEventHandler(*window, #PG_Event_MouseLeftButtonUp, @WindowMouseLeftButtonUpEventHandler())
layout = LayoutGetCurrent()
layoutmap(Str(layout)) = "window grid layout 1"
LayoutSetType(layout, #PG_Layout_Type_Grid)
LayoutSetProperty(layout, #PG_Grid_Flow, #PG_Grid_Flow_RowDense)
LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 0, 0)
LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 0, 0)
LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 0, 0) ; 200
LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 0, 0)
LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 0, 0)
LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 0, 0)
LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 0, 0)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 1, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 2, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 2, 20)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 3, 20, #PG_Grid_Percent)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 3, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 4, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 4, 20)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 5, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 6, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 7, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateColumnSize, 7, 20)
;LayoutSetProperty(layout, #PG_Grid_DefaultColumnMinSize, 0)
;LayoutSetProperty(layout, #PG_Grid_DefaultColumnSize, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_DefaultColumnMaxSize, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_DefaultRowMinSize, 0)
;LayoutSetProperty(layout, #PG_Grid_DefaultRowMaxSize, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_DefaultRowSize, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_AlignContent, #PG_Grid_AlignContent_SpaceAround)
LayoutSetProperty(layout, #PG_Grid_GapSize, 5, 5)
LayoutSetProperty(layout, #PG_Layout_Padding, 20)
;LayoutSetProperty(layout, #PG_Grid_SpanMode, #PG_Grid_SpanMode_Tight, #PG_Grid_SpanMode_Even)
;LayoutSetProperty(layout, #PG_Grid_JustifyContent, #PG_Grid_JustifyContent_SpaceAround)
;LayoutSetProperty(layout, #PG_Grid_AlignContent, #PG_Grid_AlignContent_SpaceAround)
;LayoutSetProperty(layout, #PG_Grid_JustifyItems, #PG_Grid_JustifyItems_Center)
;LayoutSetProperty(layout, #PG_Grid_AlignItems, #PG_Grid_AlignItems_Center)
For n = 1 To 28
widget = CreateWidget(0, 0, 0, 0)
item = LayoutGetItemFromWidget(widget)
If n = 1
AddEventHandler(widget, #PG_Event_MouseMove, @WidgetMouseMoveEventHandler())
AddEventHandler(widget, #PG_Event_MouseEnter, @WidgetMouseEnterEventHandler())
AddEventHandler(widget, #PG_Event_MouseLeave, @WidgetMouseLeaveEventHandler())
EndIf
If n = 2
AddEventHandler(widget, #PG_Event_MouseMove, @WidgetMouseMoveEventHandler())
AddEventHandler(widget, #PG_Event_MouseEnter, @WidgetMouseEnterEventHandler())
AddEventHandler(widget, #PG_Event_MouseLeave, @WidgetMouseLeaveEventHandler())
EndIf
; LayoutSetItemProperty(item, #PG_Layout_Item_IdealWidth, 30)
; LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, 30)
;LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 30)
;LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 30)
; LayoutSetItemProperty(item, #PG_Layout_Item_Justify, #PG_Layout_Item_Justify_Center)
; LayoutSetItemProperty(item, #PG_Layout_Item_Align, #PG_Layout_Item_Align_Center)
Next
widget = CreateTestWidget3()
item = LayoutGetItemFromWidget(widget)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnStart, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 6)
LayoutSetItemProperty(item, #PG_Layout_Item_RowStart, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 6)
;LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, #PG_Layout_FitContent)
;LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, #PG_Layout_FitContent)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, #PG_Layout_FitContent)
layout2 = LayoutGetCurrent()
layoutmap(Str(layout2)) = "grid layout 2"
LayoutSetProperty(layout2, #PG_Grid_TemplateColumnSize, 0, 0)
LayoutSetProperty(layout2, #PG_Grid_TemplateColumnSize, 0, 0)
LayoutSetProperty(layout2, #PG_Grid_TemplateColumnSize, 0, 0)
; LayoutSetProperty(layout2, #PG_Grid_TemplateColumnMinSize, 2, #PG_Grid_MaxContent)
; LayoutSetProperty(layout2, #PG_Grid_TemplateColumnMinSize, 3, #PG_Grid_MaxContent)
; LayoutSetProperty(layout2, #PG_Grid_TemplateRowMinSize, 2, #PG_Grid_MaxContent)
; LayoutSetProperty(layout2, #PG_Grid_TemplateRowMinSize, 3, #PG_Grid_MaxContent)
; LayoutSetProperty(layout2, #PG_Grid_DefaultColumnMinSize, 50)
; LayoutSetProperty(layout2, #PG_Grid_DefaultRowMinSize, 50)
LayoutSetProperty(layout2, #PG_Grid_GapSize, 5, 5)
LayoutSetProperty(layout2, #PG_Layout_Padding, 20)
For n = 1 To 12
widget = CreateWidget(0, 0, 0, 0)
item = LayoutGetItemFromWidget(widget)
If n = 1
AddEventHandler(widget, #PG_Event_MouseMove, @WidgetMouseMoveEventHandler())
AddEventHandler(widget, #PG_Event_MouseEnter, @WidgetMouseEnterEventHandler())
AddEventHandler(widget, #PG_Event_MouseLeave, @WidgetMouseLeaveEventHandler())
EndIf
; LayoutSetItemProperty(item, #PG_Layout_Item_IdealWidth, 30)
; LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, 30)
;LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 30)
;LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 30)
; LayoutSetItemProperty(item, #PG_Layout_Item_Justify, #PG_Layout_Item_Justify_Center)
; LayoutSetItemProperty(item, #PG_Layout_Item_Align, #PG_Layout_Item_Align_Center)
Next
widget = CreateTestWidget4()
item = LayoutGetItemFromWidget(widget)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnStart, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_RowStart, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, #PG_Layout_FitContent)
;LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, #PG_Layout_FitContent)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, #PG_Layout_FitContent)
layout3 = LayoutGetCurrent()
layoutmap(Str(layout3)) = "grid layout 3"
LayoutSetProperty(layout3, #PG_Grid_TemplateColumnSize, 0, 0)
LayoutSetProperty(layout3, #PG_Grid_TemplateColumnSize, 0, 0)
LayoutSetProperty(layout3, #PG_Grid_TemplateColumnSize, 0, 0)
;LayoutSetProperty(layout3, #PG_Grid_TemplateColumnMinSize, 2, #PG_Grid_MaxContent)
;LayoutSetProperty(layout3, #PG_Grid_TemplateColumnMinSize, 3, #PG_Grid_MaxContent)
;LayoutSetProperty(layout3, #PG_Grid_TemplateRowMinSize, 2, #PG_Grid_MaxContent)
;LayoutSetProperty(layout3, #PG_Grid_TemplateRowMinSize, 3, #PG_Grid_MaxContent)
;LayoutSetProperty(layout3, #PG_Grid_DefaultColumnMinSize, 50)
;LayoutSetProperty(layout3, #PG_Grid_DefaultRowMinSize, 50)
LayoutSetProperty(layout3, #PG_Grid_GapSize, 5, 5)
LayoutSetProperty(layout3, #PG_Layout_Padding, 20)
For n = 1 To 12
widget = CreateWidget(0, 0, 0, 0)
item = LayoutGetItemFromWidget(widget)
; LayoutSetItemProperty(item, #PG_Layout_Item_IdealWidth, 30)
; LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, 30)
;LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 30)
;LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 30)
; LayoutSetItemProperty(item, #PG_Layout_Item_Justify, #PG_Layout_Item_Justify_Center)
; LayoutSetItemProperty(item, #PG_Layout_Item_Align, #PG_Layout_Item_Align_Center)
Next
widget = CreateTestWidget()
item = LayoutGetItemFromWidget(widget)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnStart, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_RowStart, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, #PG_Layout_FitContent)
;LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, #PG_Layout_FitContent)
;LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, 200)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, #PG_Layout_FitContent)
;LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 100)
layout2 = LayoutGetCurrent()
layoutmap(Str(layout2)) = "flex layout"
For n = 1 To 4;000
widget = CreateWidget(380, 50, Random(100), 0)
item = LayoutGetItemFromWidget(widget)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 50)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 50)
LayoutSetItemProperty(item, #PG_Layout_Item_Margin, 5)
Next
LayoutSetCurrent(layout3)
widget = CreateTestWidget()
AddEventHandler(widget, #PG_Event_MouseMove, @WidgetMouseMoveEventHandler())
AddEventHandler(widget, #PG_Event_MouseEnter, @WidgetMouseEnterEventHandler())
AddEventHandler(widget, #PG_Event_MouseLeave, @WidgetMouseLeaveEventHandler())
item = LayoutGetItemFromWidget(widget)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnStart, 4)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_RowStart, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, #PG_Layout_FitContent)
;LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, #PG_Layout_FitContent)
;LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, 200)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, #PG_Layout_FitContent)
;LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 100)
layout2 = LayoutGetCurrent()
layoutmap(Str(layout2)) = "flex layout"
For n = 1 To 5;000
widget = CreateWidget(380, 50, Random(100), 0)
item = LayoutGetItemFromWidget(widget)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 50)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 50)
LayoutSetItemProperty(item, #PG_Layout_Item_Margin, 5)
Next
widget = CreateButtonOS2(0, 0, 100, 200)
widget = CreateTestWidget5(*window)
item = LayoutGetItemFromWidget(widget)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 50)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 50)
LayoutSetItemProperty(item, #PG_Layout_Item_Margin, 5)
CreateTestWidgetAnim(0, 0, 200, 200)
LayoutSetCurrent(layout)
;testWidget = CreateWidget(0, 0, 0, 0)
testWidget = CreateTestWidget()
item = LayoutGetItemFromWidget(testWidget)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, #PG_Layout_FitContent)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, #PG_Layout_FitContent)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 4)
LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_RowStart, 11)
;LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 2)
;LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 4)
;LayoutSetItemProperty(item, #PG_Layout_Item_Margin, 10)
layout2 = LayoutGetCurrent()
layoutmap(Str(layout2)) = "flex layout 2"
For n = 1 To 10;000
widget = CreateWidget(380, 50, Random(250), 0)
item = LayoutGetItemFromWidget(widget)
LayoutSetItemProperty(item, #PG_Layout_Item_idealWidth, 60)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 60)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 30)
LayoutSetItemProperty(item, #PG_Layout_Item_Margin, 5)
Next
LayoutSetCurrent(layout)
testWidget = CreateTestWidget()
item = LayoutGetItemFromWidget(testWidget)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, #PG_Layout_FitContent)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, #PG_Layout_FitContent)
LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 2)
LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 4)
;LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 4)
;LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 1)
LayoutSetItemProperty(item, #PG_Layout_Item_Margin, 10)
layout2 = LayoutGetCurrent()
layoutmap(Str(layout2)) = "flex layout 3"
For n = 1 To 10;000
widget = CreateWidget(380, 50, Random(250), 0) ; 250
item = LayoutGetItemFromWidget(widget)
LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 30)
LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 30)
LayoutSetItemProperty(item, #PG_Layout_Item_Margin, 5)
Next
LayoutSetCurrent(layout)
; testWidget = CreateTestWidget()
; item = LayoutGetItemFromWidget(testWidget)
; LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, #PG_Layout_FitContent)
; LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, #PG_Layout_FitContent)
; LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 2)
; LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 3)
; LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, 2)
; LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, 4)
; layout2 = LayoutGetCurrent()
; layoutmap(Str(layout2)) = "flex layout 2"
; For n = 1 To 10;000
; widget = CreateWidget(380, 50, Random(250), 0)
; item = LayoutGetItemFromWidget(widget)
; LayoutSetItemProperty(item, #PG_Layout_Item_idealWidth, 60)
; LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 60)
; LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 30)
; LayoutSetItemProperty(item, #PG_Layout_Item_Margin, 5)
; Next
; LayoutSetCurrent(layout)
;LayoutSetProperty(layout, #PG_Grid_TemplateRowSize, 9, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateRowSize, 10, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateRowSize, 11, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateRowSize, 12, #PG_Grid_MaxContent)
;LayoutSetProperty(layout, #PG_Grid_TemplateRowSize, 9, 50)
;LayoutSetProperty(layout, #PG_Grid_TemplateRowSize, 10, 50)
;LayoutSetProperty(layout, #PG_Grid_TemplateRowSize, 11, 50)
;LayoutSetProperty(layout, #PG_Grid_TemplateRowSize, 9, 10, #PG_Grid_Percent)
; testWidget = CreateWidget(0, 0, 100, 50)
; item = LayoutGetItemFromWidget(testWidget)
; LayoutSetItemProperty(item, #PG_Layout_Item_ColumnStart, 4)
; LayoutSetItemProperty(item, #PG_Layout_Item_RowStart, 9)
; testWidget = CreateWidget(0, 0, 100, 50)
; item = LayoutGetItemFromWidget(testWidget)
; LayoutSetItemProperty(item, #PG_Layout_Item_ColumnStart, 4)
; LayoutSetItemProperty(item, #PG_Layout_Item_RowStart, 10)
AddEventHandler(*window, #PG_Event_Draw, @draw())
AddEventHandler(*window, #PG_Event_DrawForeground, @drawForeground())
AddEventHandler(*window, #PG_Event_Animate, @WindowAnimateEventHandler())
StartAnimation(*window, "windowAnim")
WindowShow(*window)
AddKeyboardShortcut(*window\window, #PB_Shortcut_Down, 1)
AddKeyboardShortcut(*window\window, #PB_Shortcut_Up, 2)
AddKeyboardShortcut(*window\window, #PB_Shortcut_Left, 3)
AddKeyboardShortcut(*window\window, #PB_Shortcut_Right, 4)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Menu
Select EventMenu()
Case 1
*layout.Layout = layout
*layout\yScrollOffset - 10
WindowRedraw(*window)
Case 2
*layout.Layout = layout
*layout\yScrollOffset + 10
WindowRedraw(*window)
Case 3
*layout.Layout = layout
*layout\xScrollOffset + 10
WindowRedraw(*window)
Case 4
*layout.Layout = layout
*layout\xScrollOffset - 10
WindowRedraw(*window)
EndSelect
EndIf
;If Event = #WM_MOUSEMOVE
;*layout.Layout = layout
;*layout\yScrollOffset - 5
;callback_DrawWindow(*window)
;EndIf
If event = #PB_Event_LeftClick
; widget = CreateWidget(0, 0, 0, 0)
; item = LayoutGetItemFromWidget(widget)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_IdealWidth, 30)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, 30)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_Justify, #PG_Layout_Item_Justify_Center)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_Align, #PG_Layout_Item_Align_Center)
;
; ;LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 50)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, 20 + Random(100))
; ;LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 50)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_IdealWidth, Random(200))
; ; If Random(8) = 0
; ; col = 1 + Random(22)
; ; row = 1 + Random(3)
; ; ;Debug col
; ; ;Debug row
; ; LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, col)
; ; LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, row)
; ; EndIf
; *window\callback_ResizeWindow(*window)
; *window\callback_DrawWindow(*window)
EndIf
If event = #PB_Event_RightClick
; ;widget = CreateWidget(0, 0, 0, 0)
; testWidget = CreateTestWidget()
; item = LayoutGetItemFromWidget(testWidget)
; ;item = LayoutGetItemFromWidget(widget)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 50)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_IdealHeight, 100)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 50)
; ;LayoutSetItemProperty(item, #PG_Layout_Item_IdealWidth, 200)
; LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, #PG_Layout_FitContent)
; LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, #PG_Layout_FitContent)
; ;If Random(8) = 0
; col = 1 + Random(6)
; row = 1 + Random(3)
; ;Debug col
; ;Debug row
; LayoutSetItemProperty(item, #PG_Layout_Item_ColumnSpan, col)
; LayoutSetItemProperty(item, #PG_Layout_Item_RowSpan, row)
; ;EndIf
;
;
; layout2 = LayoutGetCurrent()
;
; LayoutSetCurrent(layout2)
; For n = 1 To 10;000
; widget = CreateWidget(380, 50, Random(250), 0)
; item = LayoutGetItemFromWidget(widget)
; LayoutSetItemProperty(item, #PG_Layout_Item_MinWidth, 100)
; LayoutSetItemProperty(item, #PG_Layout_Item_MinHeight, 50)
; LayoutSetItemProperty(item, #PG_Layout_Item_Margin, 5)
; Next
; LayoutSetCurrent(layout)
;
; *window\callback_ResizeWindow(*window)
; *window\callback_DrawWindow(*window)
EndIf
Until Event = #PB_Event_CloseWindow; Or Event = #PB_Event_RightClick
StopProGUI()
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
-
- Addict
- Posts: 1675
- Joined: Sun Dec 12, 2010 12:36 am
- Location: Somewhere in the midwest
- Contact:
Re: ProGUI V3 Alpha Sneak Peek!
No problem. I understand it's a lot of work.
Re: ProGUI V3 Alpha Sneak Peek!
Cheers mate

Just a quick update on the alpha progress. I've spent the past couple of weeks fixing some rendering bugs with the Win32 common controls - all working nicely now. Last night I managed to mostly get all the common controls working with automatic per monitor DPI updating using a HFONT caching mechanism where the #WM_SETFONT message is intercepted and either a new font is created and cached (based on the current DPI) or an alternative DPI font from the cache is used. Purebasic's SetGadgetFont() works transparently this way. The richedit (Editor Gadget) and IP Address gadgets are misbehaving so I need to fix that. I also need to think of a good way to do multiple DPI images before the alpha is ready, at the moment all images, brushes and imageborders are scaled based on 96dpi so that's kind of where I am at the moment.
Cheers! Chris.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
There's also a new '#PG_Event_DPI' event that gets sent to any widgets that are currently visible when the parent window's DPI changes, and if any widgets become visible (through scrolling or occlusion) then the event is sent. This allows you to handle custom / manual DPI changes if needed (and is the backbone for OS widgets)
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
A question for Chris if I may. Firstly, congratulations on your work. Is the scope of ProGUI intended to improve the UI of business applications — not utilities, but typical line of business applications — over what we have with the PureBasic controls already? Thanks.
Re: ProGUI V3 Alpha Sneak Peek!
Hi PBJim yep (and thanks!) so you design your UI using the layout engines, you don't need to handle any resize callbacks or worry about DPI scaling so straight off the bat coding a new application or porting an old one is a piece of cake. I'd reccomend looking at https://www.w3schools.com/css/css3_flexbox.asp and https://www.w3schools.com/css/css_grid.asp the functionality is around 98% the same with some improvements for grid such as a better 'auto' algorithm that can handle minumum and maximum widths/heights.PBJim wrote: Sun Apr 21, 2024 12:05 am A question for Chris if I may. Firstly, congratulations on your work. Is the scope of ProGUI intended to improve the UI of business applications — not utilities, but typical line of business applications — over what we have with the PureBasic controls already? Thanks.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
I've designed ProGUI V3 around the mantra of being able to easily create custom Widgets "Give a Man a Fish, and You Feed Him for a Day. Teach a Man To Fish, and You Feed Him for a Lifetime" with the layout engines doing all the heavy lifting. Think of a PureBasic canvas gadget on steroids with an easy GFX API that is all GPU driven. You can actually use a PureBasic Canvas gadget too 

ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
Thanks for the reply Chris, appreciate the information. I haven't tried ProGUI yet, so this assumption may be wrong, but I guess that screen layout is organised by relative position, rather than the X, Y coodinates of PB. Will you announce a release when the appropriate time comes? Probably best to wait until then before I begin to try it. Thanks again, Jim.PrincieD wrote: Sun Apr 21, 2024 12:29 am Hi PBJim yep (and thanks!) so you design your UI using the layout engines, you don't need to handle any resize callbacks or worry about DPI scaling so straight off the bat coding a new application or porting an old one is a piece of cake. I'd reccomend looking at https://www.w3schools.com/css/css3_flexbox.asp and https://www.w3schools.com/css/css_grid.asp the functionality is around 98% the same with some improvements for grid such as a better 'auto' algorithm that can handle minumum and maximum widths/heights.
Re: ProGUI V3 Alpha Sneak Peek!
No worries Jim. With the basic layout widgets are postioned by absolute X, Y coordinates and with the Flex and Grid layouts widgets are positioned based on the order they were created / added to the layout (and the properties of the layout).PBJim wrote: Sun Apr 21, 2024 8:48 pmThanks for the reply Chris, appreciate the information. I haven't tried ProGUI yet, so this assumption may be wrong, but I guess that screen layout is organised by relative position, rather than the X, Y coodinates of PB. Will you announce a release when the appropriate time comes? Probably best to wait until then before I begin to try it. Thanks again, Jim.PrincieD wrote: Sun Apr 21, 2024 12:29 am Hi PBJim yep (and thanks!) so you design your UI using the layout engines, you don't need to handle any resize callbacks or worry about DPI scaling so straight off the bat coding a new application or porting an old one is a piece of cake. I'd reccomend looking at https://www.w3schools.com/css/css3_flexbox.asp and https://www.w3schools.com/css/css_grid.asp the functionality is around 98% the same with some improvements for grid such as a better 'auto' algorithm that can handle minumum and maximum widths/heights.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
Hi guys, fixed the richedit DPI issues - working perfectly. The IP address control (SysIPAddress32) is partially fixed, as much as I'm willing to fix at the moment - a classic example of varying degrees of quality when it comes to Microsoft and the teams that worked on each common control. The SysIPAddress32 common control has a parent window with 4 sibling 'Edit' controls, however the HFONT that is passed to the parent window isn't the HFONT that you will get back. The coders that worked on this control in their infinite wisdom
decided they would create a new HFONT based on the one passed except with some kind of kerning to make the dots (rendered IP address dots between the characters) expand. So rather than just get the width of the string, the width is added to the font itself (fuck me). You can test this out yourself by doing a SetGadgetFont on the IP address gadget then do a GetGadgetFont.
anyway I'm currently working on Widget mouse pointers and the Window borderless flags and making sure that's all working correctly.
For handling multiple DPI image versions I'm thinking the best way to do it is adding an extra DrawDPI() command where you can specify 'None', 'Auto' or DPI at any time - currently all the GFX API drawing commands scale the DPI automatically based on Device Independant Pixels (96dpi) and the OutputImg() command already has an optional DPI parameter (a good use case is printing) so BeginDraw(OutputImg(Img, DPI = #Null)). So in conjunction with that adding another 'AddImgDPIImg()" command where you can add another Img to an existing Img and specify the DPI and extending the LoadImg() command where the path can be semicolon separated with each semicolon being a delimiter for the next logical DPI starting at 96 e.g. "testIcon.png; testIcon_120.png; testIcon_144.png.."
Let me know your thoughts guys!
Chris.


For handling multiple DPI image versions I'm thinking the best way to do it is adding an extra DrawDPI() command where you can specify 'None', 'Auto' or DPI at any time - currently all the GFX API drawing commands scale the DPI automatically based on Device Independant Pixels (96dpi) and the OutputImg() command already has an optional DPI parameter (a good use case is printing) so BeginDraw(OutputImg(Img, DPI = #Null)). So in conjunction with that adding another 'AddImgDPIImg()" command where you can add another Img to an existing Img and specify the DPI and extending the LoadImg() command where the path can be semicolon separated with each semicolon being a delimiter for the next logical DPI starting at 96 e.g. "testIcon.png; testIcon_120.png; testIcon_144.png.."
Let me know your thoughts guys!
Chris.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
Hi guys, another quick update. There's a new WidgetSetCursor() command that behaves the same as PB's canvas gadget along with a new #PG_Window_BackgroundDrag flag for the CreateWindow() command that works with borderless windows - if you look at the dev log videos on youtube you can see previously that was hard coded (Arrows cursor even when hovering over an OS control). I've also made some good progress on multiple DPI versions of images and now thinking rather than specify a DPI value and an image you literally just add another image to an existing image so something like ImgAddOtherSize(Img, SrcImg) and then commands like DrawImg(Img, x.d, y.d, Width.d, Height.d, Opacity.f) will select the nearest (with higher resolution images taking priority when down scaling) based on the Width and Height (the DPI scaled width and height pixels) - this should make icon images (16x16, 24x24, 32x32 etc) work automatically e.g. DrawImg(Img, x, y, 16, 16, 1.0) at 120dpi would select the icon 24x24 (if exists).
Chris.
Chris.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
Just thought I'd mention too, with the GFX API the Img structure has an internal reference count so commands like CreateImgBrush or CreateImgBorder increment the internal reference count rather than make a copy of the Img - FreeImg() decrements the internal reference count and only when it's <= 0 do resources get deallocated. This allows you to draw directly to an image (if you have a handle) and all brushes etc that use it update immediately. For example you could have an ImgBorder that a bunch of Widgets use, you can draw directly to the Img that the Border is set to and modify it in 'real-time' if you wanted.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha Sneak Peek!
Hi, PrincieD
I've purchased a license a long time ago (2010/10/24 from my archive, my old mail is y**l*.com.tw), but my mail address is long gone, how do I caontact you(still have theoriginal purchase mail), the last mail I recieve is around v2.01/1.41.
How do I contact you for further information, my user name is "Tsai **** Tzung", thanks!
I've purchased a license a long time ago (2010/10/24 from my archive, my old mail is y**l*.com.tw), but my mail address is long gone, how do I caontact you(still have theoriginal purchase mail), the last mail I recieve is around v2.01/1.41.
How do I contact you for further information, my user name is "Tsai **** Tzung", thanks!
This field was left intentionally as signature.