XML Dialogue with runtime-drawn custom image-gadgets?

Just starting out? Need help? Post your questions and find answers here.
User avatar
Kukulkan
Addict
Addict
Posts: 1396
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

XML Dialogue with runtime-drawn custom image-gadgets?

Post by Kukulkan »

Hello,

I'm still stuck in the conception of my layout. I like to use OpenXMLDialog() to do the GUI. But I also like to use self drawn gadgets (http://www.purebasic.fr/english/viewtop ... 12&t=49192).

In the meantime, my self drawn gadgets are drawing with DPI awareness. The result is, that the images created in the background are of different size (dependig of DPI).

But
1) how to use my own image gadgets together with OpenXMLDialog and
2) How to make the XML dialogue respect the size of the buttons (depending on DPI, not hardcoded in XML)?

Also still stuck in the question, how to use some image as header in a DPI aware manner (http://www.purebasic.fr/english/viewtop ... =7&t=57737).

Please, can anyone tell me the right way to do? Or do I really have to stop using XML dialogues because of missing functionality?

Best,

Kukulkan
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: XML Dialogue with runtime-drawn custom image-gadgets?

Post by RASHAD »

Hi Kukulkan

Code: Select all

CompilerIf #PB_Compiler_Unicode
  #XmlEncoding = #PB_UTF8
CompilerElse
  #XmlEncoding = #PB_Ascii
CompilerEndIf

#Dialog = 0
#Xml = 0

Global Arial24

Arial24=LoadFont(1, "Arial", 24)
If Arial24=0
  Debug "Error font"
  End
EndIf


Procedure.s NewTextWidth(text$, font=-1, margin=0)
  ;font=-1 => Font sytem
  Protected W
 
 
  If CreateImage(0, 200,200)
    StartDrawing(ImageOutput(0))
    If font <> -1
      DrawingFont(font)
    EndIf
    W=TextWidth(text$) + margin
    StopDrawing()
  Else
    Debug "Error in NewTextWidth()"
    End
  EndIf
  FreeImage(0)
  ProcedureReturn "width='"+Str(W)+"' "
EndProcedure

Procedure.s NewTextHeight(text$, font=-1, margin=0)
  ;font=-1 => Font sytem
  Protected H
 
  If CreateImage(0, 200,200)
    StartDrawing(ImageOutput(0))
    If font <> -1
      DrawingFont(font)
    EndIf
    H=TextHeight(text$) + margin
    StopDrawing()
  Else
    Debug "Error in NewTextHeight()"
    End
  EndIf
  FreeImage(0)
  ProcedureReturn "height='"+Str(H)+"' "
EndProcedure


XML$ = "<window id='#PB_Any' name='test' text='test' minwidth='auto' minheight='auto' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
       "  <panel>" +
       "    <tab text='Tab'>" +
       "      <vbox expand='item:2'>" +
       "        <hbox>" +
       "          <button name='but1' text='Button 1' "  +
       NewTextWidth("Button 1",  Arial24, 60) +
       NewTextHeight("Button 1", Arial24, 60) +
       "           /> " +
       "          <checkbox name='check1' text='CheckBox 1'/>" +
       "        <singlebox expand='no' align='center,right'>" +
       "          <button name='but2' text='Button 2' " +
       "           /> " +
       "        </singlebox>" +
       "        </hbox>" +
       "        <editor text='Ok...&#xA;&#xA;Test' height='150'/>" +
       "      </vbox>" +
       "    </tab>" + 
       "  </panel>" +
       "</window>"

;*************************************************************
;************** Comment the next to see the difference **************
OpenLibrary(0,"User32.dll")
*Result_1 = GetFunction(0,"IsProcessDPIAware")
IsDPI= CallFunctionFast(*Result_1)
Debug IsDPI
If IsDPI = 0
      *Result_2 = GetFunction(0,"SetProcessDPIAware")
       CallFunctionFast(*Result_2)
       IsDPI= CallFunctionFast(*Result_1)
       Debug IsDPI
EndIf
CloseLibrary(0)
;**************************************************************
;**************************************************************

If CatchXML(#Xml, @XML$, StringByteLength(XML$), 0, #XmlEncoding) And XMLStatus(#Xml) = #PB_XML_Success
 
  If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "test")
   
    SetGadgetFont(DialogGadget(#Dialog, "but1"), FontID(1))
    ;SetGadgetText(DialogGadget(#Dialog, "but1"), "azerty")
   
   
    Repeat
      Event = WaitWindowEvent()
    Until Event = #PB_Event_CloseWindow
   
  Else 
    Debug "Error  -Dialog- : " + DialogError(#Dialog)
  EndIf
Else
  Debug "Error XML : " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
EndIf
Edit :Added check for DPI
Egypt my love
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2137
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Re: XML Dialogue with runtime-drawn custom image-gadgets?

Post by Andre »

Well done! :D

Works on MacOS too, but here I needed to comment the Windows-specific code. That's why I did the following 'CompilerIf' statement:

Code: Select all

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  OpenLibrary(0,"User32.dll")
  *Result_1 = GetFunction(0,"IsProcessDPIAware")
  IsDPI= CallFunctionFast(*Result_1)
  Debug IsDPI
  If IsDPI = 0
        *Result_2 = GetFunction(0,"SetProcessDPIAware")
         CallFunctionFast(*Result_2)
         IsDPI= CallFunctionFast(*Result_1)
         Debug IsDPI
  EndIf
  CloseLibrary(0)
CompilerElse
  Debug "DPI awareness isn't supported on non-Windows platforms for now!"
CompilerEndIf
Is there any solution for MacOS yet, to support DPI-awareness there too in this code?
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
User avatar
Kukulkan
Addict
Addict
Posts: 1396
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: XML Dialogue with runtime-drawn custom image-gadgets?

Post by Kukulkan »

Hi RASHAD and Andre,

thank you for your examples, but it does not really fit my needs. I can not pre-calculate the sizes during runtime, as I include the XML during compile-time (IncludeBinary). I might use some kind of place-holders replacement (like I do for language strings) but I do not like to handle lots of elements like this as it complicates the source very much.

This also does not solve my problem of images and ImageGadgets() not resizing depending on DPI settings. I also would have to resize the image manually and set width and height manually.

By the way, the IsProcessDPIAware() function always returns 1 for me, so the API SetProcessDPIAware() is never called. Don't know why it is activated for me all the time (PB 5.30, 32 Bit). But I do not care as I like to have all my programs to be DPI aware anyway.

Also, I believe the reason of a layout engine is to prevent such manual calculation! What is the benefit of such engine if I need to calculate sizes and borders manually to support modern UI?

Example:

Code: Select all

CompilerIf #PB_Compiler_Unicode
  #XmlEncoding = #PB_UTF8
CompilerElse
  #XmlEncoding = #PB_Ascii
CompilerEndIf

#Dialog = 0
#Xml = 0
#Image = 0

XML$ = "<window id='#PB_Any' name='test' text='test' minwidth='auto' minheight='auto' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
       "  <vbox expand='item:2'>"+
       "    <image name='imgTest' height='50' flags='' />"+
       "    <vbox>"+
       "      <button text='Example UI content' />"+
       "      <button text='Example UI content' />"+
       "    </vbox>"+
       "  </vbox>"+
       "</window>"


If CatchXML(#Xml, @XML$, StringByteLength(XML$), 0, #XmlEncoding) And XMLStatus(#Xml) = #PB_XML_Success
 
  If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "test")
    ; create some image with content
    CreateImage(#Image, 1024, 50, 24, RGB(255,255,255))
    StartDrawing(ImageOutput(#Image))
    Line(0,0,ImageWidth(#Image), ImageHeight(#Image), RGB(255,0,0))
    StopDrawing()
    ; update image gadget with image
    imgGad = DialogGadget(#Dialog, "imgTest")
    SetGadgetState(imgGad, ImageID(#Image))
   
    Repeat
      Event = WaitWindowEvent()
    Until Event = #PB_Event_CloseWindow
   
  Else
    Debug "Error  -Dialog- : " + DialogError(#Dialog)
  EndIf
Else
  Debug "Error XML : " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
EndIf
As you can see, the buttons fonts and borders etc are scaling, but the image does not scale. If a layout is based on such picture (like a nice header with logo or some special divider image), it looks really weird on displays with 150 or even more DPI (4K Monitors are coming). If I do not set the image height with a fixed value, the image is not displayed (height=0). As I load the image and the XML from binary content during runtime, I do not like to parse the XML to set sizes during runtime. A layout engine is to help me on such and not to force me doing the DPI calculations by myself.

There are two solutions (I guess):
1) The XML Dialog engine also multiplies the width/height/minwidth/minheight/maxwidth/maxheight values with the DPI factor. It also scales the content of images and canvas automatically.
2) The XML Dialog engine is using the current image-size to re-calculate the complete layout after I changed the image content.

Solution 2 would let me scale the image manually (what I would accept). But sadly, the layout does not care about the image sizes after it is once calculated. This also would not fix the issue for several other things using fixed values (width/height/minwidth/minheight/maxwidth/maxheight).

Sadly, both solutions need Fred to enhance the layout engine.

I reported several problems in the past. Most of them regarding the XML layout, but he never changed anything :-(

http://www.purebasic.fr/english/viewtop ... =7&t=57737
http://www.purebasic.fr/english/viewtop ... =7&t=57280
http://www.purebasic.fr/english/viewtop ... =3&t=60506
http://www.purebasic.fr/english/viewtop ... =7&t=60380
http://www.purebasic.fr/english/viewtop ... =7&t=59929
http://www.purebasic.fr/english/viewtop ... 13&t=59261
http://www.purebasic.fr/english/viewtop ... =3&t=57704

I think the XML Dialog is not really usable in the moment as it has too many open issues :-(

Kukulkan
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: XML Dialogue with runtime-drawn custom image-gadgets?

Post by RASHAD »

Hi Kukulkan
- Next snippet are always award of DPI
- The Image is resized with windows

If you want your application to be DPI compliant we can estimate
the Val & Hal Scales no matter what the DPI is
then multiply the dimensions with the scale when needed

Just post some snippet (Make it simple :D )
And your requirements

Code: Select all

CompilerIf #PB_Compiler_Unicode
  #XmlEncoding = #PB_UTF8
CompilerElse
  #XmlEncoding = #PB_Ascii
CompilerEndIf

#Dialog = 0
#Xml = 0
#Image = 0

Global imgGad

XML$ = "<window id='#PB_Any' name='test' text='test' minwidth='auto' minheight='auto' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
       "  <vbox expand='item:2'>"+
       "    <image name='imgTest' height='50' flags='' />"+
       "    <vbox>"+
       "      <button text='Example UI content' />"+
       "      <button text='Example UI content' />"+
       "    </vbox>"+
       "  </vbox>"+
       "</window>"
       
Procedure SizeWindowHandler()
    xx = GadgetWidth(imgGad)
    CreateImage(#Image, xx,50, 24, RGB(255,255,255))
    StartDrawing(ImageOutput(#Image))
        Line(0,0,xx,50, RGB(255,0,0))
    StopDrawing()
    SetGadgetState(imgGad, ImageID(#Image))
EndProcedure

OpenLibrary(0,"User32.dll")
  *Result_2 = GetFunction(0,"SetProcessDPIAware")
  CallFunctionFast(*Result_2)
CloseLibrary(0)

If CatchXML(#Xml, @XML$, StringByteLength(XML$), 0, #XmlEncoding) And XMLStatus(#Xml) = #PB_XML_Success
 
  If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "test")
    ; create some image with content
    imgGad = DialogGadget(#Dialog, "imgTest")
    xx = GadgetWidth(imgGad)
    CreateImage(#Image, xx ,50, 24, RGB(255,255,255))
    StartDrawing(ImageOutput(#Image))
    Line(0,0,xx, 50, RGB(255,0,0))
    StopDrawing()
    ; update image gadget with image
    
    SetGadgetState(imgGad, ImageID(#Image))
   BindEvent(#PB_Event_SizeWindow ,@SizeWindowHandler() ) 
    Repeat
      Event = WaitWindowEvent()
    Until Event = #PB_Event_CloseWindow
   
  Else
    Debug "Error  -Dialog- : " + DialogError(#Dialog)
  EndIf
Else
  Debug "Error XML : " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
EndIf

Egypt my love
User avatar
Kukulkan
Addict
Addict
Posts: 1396
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: XML Dialogue with runtime-drawn custom image-gadgets?

Post by Kukulkan »

Hi RASHAD,

thank you again for your help. But sadly my English seems so bad that I even can not describe my problem in a way that is understood :(

The red line is just an example to see the image. I use a bitmap header with logo on the left. So I do not redraw it each time. I do not have such problem like you try to solve. :|

The first problem is, that all elements are getting bigger except the image!

Windows 100% to Windows 150%:
http://img4web.com/view/W8X915

As you can see in the screenshot, the image is always 50 pixels in height. But on a 4K screen, 50 pixels are way to less for the dialogue. The image needs to be 75 pixels in height on 150%! The layout engine has to scale such pixel values regarding the DPI settings. Even if the image is getting blurred because of resizing. But it does not scale!

The second problem is, that I like to use self drawn image gadgets as buttons (see first post). But I can not use them in XML dialogues. At least, I don't know how to insert existing DPI aware ImageGadgets if the XML dialogue is always using a fixed pixel size...

Sorry for being that unclear...

Kukulkan
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: XML Dialogue with runtime-drawn custom image-gadgets?

Post by RASHAD »

Hi again mate
Is the next snippet solves your first problem?

Code: Select all

CompilerIf #PB_Compiler_Unicode
  #XmlEncoding = #PB_UTF8
CompilerElse
  #XmlEncoding = #PB_Ascii
CompilerEndIf

#Dialog = 0
#Xml = 0
#Image = 0

Global imgGad

XML$ = "<window id='#PB_Any' name='test' text='test' minwidth='auto' minheight='auto' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
       "  <vbox expand='yes'>"+
       "      <canvas name='imgTest'  height='20' />"+
       "      <button text='Example UI content' />"+
       "      <button text='Example UI content' />"+
       "  </vbox>"+
       "</window>"       
LoadImage(0,"g:\girl24.bmp")
ResizeImage(0,32,32)
If CatchXML(#Xml, @XML$, StringByteLength(XML$), 0, #XmlEncoding) And XMLStatus(#Xml) = #PB_XML_Success
 
  If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "test")
    ; create some image with content
    imgGad = DialogGadget(#Dialog, "imgTest")
    StartDrawing(CanvasOutput(imgGad)) 
    DrawImage(ImageID(0),0,0)
    StopDrawing()
    ; update image gadget with image
   ;SetGadgetAttribute(imgGad, #PB_Button_Image,ImageID(#Image))

   ;BindEvent(#PB_Event_SizeWindow ,@SizeWindowHandler() )
    Repeat
      Event = WaitWindowEvent()
    Until Event = #PB_Event_CloseWindow
   
  Else
    Debug "Error  -Dialog- : " + DialogError(#Dialog)
  EndIf
Else
  Debug "Error XML : " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
EndIf
Egypt my love
User avatar
Kukulkan
Addict
Addict
Posts: 1396
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: XML Dialogue with runtime-drawn custom image-gadgets?

Post by Kukulkan »

Hi RASHAD,

No, sadly not. In your example, the ImageGadget "imgTest" of the XML dialogue is used and the image is only assigned to this gadget. But I have to include existing image gadgets. It is more like injecting existing gadgets to the layout engine...

Best,

Volker
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: XML Dialogue with runtime-drawn custom image-gadgets?

Post by RASHAD »

Hi Kukulkan
If I understood you correctly you want to use your own hand made Buttons with a window created by XML Dialogue
If that is true the next may help

Code: Select all

  ; As we embedded xml directly in the source, the encoding of special characters will vary if we are in unicode mode or not. 
  ; So ensure to use the correct one. This is not needed if the XML is read from an external file or directly included
  ; with IncludeBinary.
  ;
  CompilerIf #PB_Compiler_Unicode
    #XmlEncoding = #PB_UTF8
  CompilerElse 
    #XmlEncoding = #PB_Ascii
  CompilerEndIf
  
  #Dialog = 0
  #Xml = 0
  
  XML$ = "<window id='#PB_Any' name='test' text='Gridbox' minwidth='auto' minheight='auto' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
         "    <gridbox columns='4' colexpand='no' rowexpand='no'>" +
         "          <empty name='Empty' width='60' height='60' colspan='4'/>" +
         "          <button text='Button 1' />" +
         "          <button text='Button 2' />" +
         "          <button text='Button 3' />" +
         "          <button text='Button 4' />" +
         "    </gridbox>" +
         "  </window>"
         
 ;Remove the next commented lines if you want to disable the DPI effect        
; OpenLibrary(0,"User32.dll")
;   *Result_2 = GetFunction(0,"SetProcessDPIAware")
;   CallFunctionFast(*Result_2)
; CloseLibrary(0)

LoadFont(0,"Arial",12,#PB_Font_HighQuality)

  If CatchXML(#Xml, @XML$, StringByteLength(XML$), 0, #XmlEncoding) And XMLStatus(#Xml) = #PB_XML_Success
    
    If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "test")
      LoadImage(0,"g:\girl24.bmp")
      ResizeImage(0,60,60)
      iMG = ImageGadget(#PB_Any,8,8,60,60,ImageID(0))
      tXT = TextGadget(#PB_Any,75,8,100,24,"Kukulkan",#PB_Text_Center|#PB_Text_Border)
      SetGadgetFont(tXT,FontID(0))
      SetGadgetColor(tXT,#PB_Gadget_BackColor,$CBFEFB)
      SetGadgetColor(tXT,#PB_Gadget_FrontColor ,#Red)

      Repeat
        Event = WaitWindowEvent()
      Until Event = #PB_Event_CloseWindow 
      
    Else  
      Debug "Dialog error: " + DialogError(#Dialog)
    EndIf
  Else
    Debug "XML error: " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
  EndIf
Egypt my love
User avatar
Kukulkan
Addict
Addict
Posts: 1396
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: XML Dialogue with runtime-drawn custom image-gadgets?

Post by Kukulkan »

Hi RASHAD,

you are simply creating additional gadgets. But they are not part of the resizing engine!

Just set colexpand='yes' rowexpand='yes' for the gridbox and you see all gadgets resizing and moving, but yours do not. Because they are not part of the layout engine. But if I use self-drawn buttons (runtime-created ImageGadgets), they have to act like the others (resize, move etc.). This is what I called "injected" to the layout engine. The runtime created gadgets need to be part of the layout engine to act like the other content.

And this is also, where the other problem comes up. Even if I manage to inject them to the layout engine, ImageGadgets() do not resize with the DPI settings. A normal button resizes with DPI settings, but ImageGadgets don't. So my gadget drawing respects DPI, but the image-containers (ImageGadgets from XML dialog) do not. This is the second issue.

I think this is not to get solved by some workaround. I'm already in contact with Fred to find a solution. And I will not use my own drawn buttons. The injection to the layout engine seems impossible. If DPI awareness is solved, I may rewrite the button functions to draw on an existing ImageGadget from the XML dialogue.

But thank you very much for your patient help!!!!

Best,

Kukulkan
Post Reply