Object-Oriented GUI Library

Headers, Bindings, Libraries for use with FreeBASIC, Please include example of use to help ensure they are tested and usable.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

Josep Roca wrote:
EDIT: Also having trouble trying to find which FB header file declares the functions for DPI awareness? I've made searches within the inc\win folder, and I've even downloaded José's library to see if I could find the header file used, but I found nothing... Process-level functions are defined within the shellscalingapi.h header file for C[++], and I've even checked whether there is a header file called "shcore.bi" - still nothing...
They belong to the WinUser header file, but they have not been included in the FB .bi files. Therefore, you have to call them dynamically, e.g.

Code: Select all

' ========================================================================================
' Sets the current process as dots per inch (dpi) aware.
' Note: SetProcessDPIAware is subject to a possible race condition if a DLL caches dpi
' settings during initialization. For this reason, it is recommended that dpi-aware be set
' through the application (.exe) manifest rather than by calling SetProcessDPIAware.
' Return value: TRUE on success; FALSE on failure.
' ========================================================================================
PRIVATE FUNCTION AfxSetProcessDPIAware () AS BOOLEAN
   DIM AS ANY PTR pLib = DyLibLoad("user32.dll")
   IF pLib = 0 THEN EXIT FUNCTION
   DIM pProc AS FUNCTION () AS LONG
   pProc = DyLibSymbol(pLib, "SetProcessDPIAware")
   IF pProc = 0 THEN EXIT FUNCTION
   FUNCTION = pProc()
   DyLibFree(pLib)
END FUNCTION
' ========================================================================================
Thanks for the help! I need to begin to remind myself this if I can't find a function within the header files!
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

ANNOUNCEMENT

Version 2.0 is currently postponed.

I've done a bit of a stupid thing: I've kinda made the OGL harder to understand and use effectively. I will re-program my child control management portion of the parent window class (read: all of it). It will make the 2.x series more understandable and involves cutting back on the amount of typing programmers (the developer and the library's users) has to make.

Technically Details
I scrapped inheritance. Some may see it as a bad thing (which it is, if you want something to be made much simpler)...

This however cannot be done because of the way that the OGL is now heading.

What's bad is my child control management system within the class. There are numerous flaws, but the worst definitely has to be: separating all the different types of controls (e.g. button, label) in separate protected arrays, which means I have had to write different versions of the same function just for each different control. It has lead to this:

Code: Select all

'OGL 1.x code
textbox.caption = "Hello World!"

'OGL 2.x code
window.textbox_caption(tbci) = "Hello World!" 'tbci is like an OGL handle for the textbox control

'OGL 2.x code: what I plan to do:
window.caption(tbci) = "Hello World!"
I plan to create one dynamic protected array for all the child controls. I will make it two dimensional:

Code: Select all

child_controls(x, 0) 'access a control's, namely x', handle
child_controls(x, 1) 'access a control's, namely x', TYPE: ie button, label, or textbox
This will cut down on the amount of code required for the OGL, and will reduce the time spent to maintain it and fix any errors that might crop up. Instead of coding multiple versions of the same function, just code one function, but within it, performs slightly different code for each control type (which can be accessed using [x, 1], and the control's handle; [x, 0]).

To put it into perspective, the amount of data the OGL 1.1 header takes up is around 38KB. OGL 2.0? Around 76KB (it used to be over 80KB before I began to fine-tune it): and without really adding anything new (I will include new things for the OGL: don't get too disappointed just yet ;D).

So yeah, I'm afraid 2.x is not coming any time soon :(.

Thanks for your support.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

Notice
Information provided in the third tutorial is incorrect.
It says this:
Low-Order Word | High-Order

0101010101010101|0101010101010101

\---32-bit Value---/

And it is in reality

High-Order Word | Low-Order

0101010101010101|0101010101010101

\---32-bit Value---/

Initial post will be updated, but I will not fix this problem in this version of the doc. This problem is fixed in the new version of the doc, not yet released.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

I'm very excited to announce that the OGL 2.0 is almost complete!

I've finished the new 2.0 header file and it's very good!

However, there is still the doc and examples to do, as well as reorganising the repository a bit.

I've done a substantial amount on the doc already, though, including a new and well improved Windows API tutorial, which I hope will aid beginners (lol I'm still a beginner tbh :D). I've written around 4/5 of it as of now, but there's quite a bit of updating to do since I temporarily stopped writing the doc.

Once this new version is out: I'm gonna have a little rest. I've been working on the OGL literally all my spare time (it was time well spent and enjoyed every minute of it!), but I'm quite tired! lol...

Anyway, once I release this fresh new start of the OGL, everything will be licensed under the 3-Clause BSD License except:
  • Extracts from the MSDN within the doc. I don't own these extracts, and therefore they aren't licensed under the OGL
  • The XML manifest file which comes with the OGL to improve its look. I, again, am not claiming ownership over this file.
But the following will be released under the 3-Clause BSD license:
  • The OGL.bi header file.
  • The doc file, including any images within it. This time, I'll also release the HelpNDoc project file for those who want to edit the doc according to what the license allows.
  • Images, they come with the examples.
  • Example code files and binary executables.
Thanks for all your support.

Edit: once I get back to extending the OGL, my first priority is to get cracking with making it high-dpi aware.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

Version 2.0 Officially Released!

Please check the repository!
kcvinu
Posts: 232
Joined: Oct 07, 2015 16:44
Location: Keralam, India

Re: Object-Oriented GUI Library

Post by kcvinu »

Thanks. I appreciate your effort to improve OGL. Let me look the new version.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

kcvinu wrote:Thanks. I appreciate your effort to improve OGL. Let me look the new version.
Hope it's still good XD!
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

Hi guys, I'm coming back to the OGL to make it High-DPI aware. I can't give a date of the release of 2.1 but it should come out by next month if I can get it going quite easily. Any help on the subject will be appreciated (as I know next to nothing about the issue). If one could give me some details concerning:
  • How to test for this feature. I.e. I can make OGL windows High-DPI aware, but how can I make sure that it actually works? I heard that one can change the DPI setting dynamically through the control panel, but when I do, what should I expect to see if my windows are High-DPI aware?
  • How to implement this feature. I will be working with the MSDN website, so I should be able to work out what to do there, but if you would like to give help, I will be more than grateful!
  • What the benefits are of implementing this feature. In all honesty, I cannot yet see a good reason to incorporate this into the OGL. The reason why I'm implementing this at all is because it has been requested. Again, there are some points over at MSDN, but all that seemed to shed light on was if the user were to change the DPI setting while the app is running. Other than that, I don't see a reason why I should. Windows adjusts according to settings, right, so if you do change the setting, then open an OGL app, the windows will be adjusted?! Please can any of you teach me what it means to be High-DPI aware?
I may also fix a few known "bugs" (they are listed in Wishlist.md in the repository), as well as incorporate this feature.

Thanks for your support.

EDIT:

OK, have re-read the MSDN pages and have come across the following points:
  • This feature would be useful for those with multiple monitors with different DPI settings, and for those who have changed the DPI setting for their monitor/s. This would make the OGL able to rescale items appropriately, I will provide this functionality through some default scaling method.
  • Josep Roca's post described the use of the SetProcessDPIAware function, though there is also a SetProcessDPIAwareness function. Do I understand correctly that the only way through messages to see if the DPI setting has been changed, is with the WM_DPICHANGED message? The MSDN page says that this is only suitable for the latter DPIAwareness function with the PROCESS_PER_MONITOR_DPI_AWARE value passed to it? The tutorials at MSDN say to use the DPIAwareness function, and that "this supersedes SetProcessDPIAware": is this the case, or can I use the DPIAware function?
  • I have already implemented a makedpiaware function within the OGL namespace. Since this function uses SetProcessDPIAware, there are no arguments, and I don't know what this function really does! Does it make the process PER_MONITOR or SYSTEM_DPI_AWARE?!
Tutorial page.

Would appreciate some help with this ASAP.
St_W
Posts: 1618
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: Object-Oriented GUI Library

Post by St_W »

DPI settings are especially used for high-resolution displays (e.g. what Apple calls "retina" displays). If UI elements wouldn't be (up)scaled everything would be very small due to the high resolution. So for higher resolution displays also a higher-resolution-UI is needed.

An application that is DPI aware must adapt its content accordingly to the DPI-Settings, i.e. provide high-resolution UI if necessary. If an application is not declared as DPI aware then Windows automatically tries to scale the application window contents (for DPI settings other than 100%), which usually results in slightly blurry display and thus is not really good.

As you've said you can use the methods SetProcessDPIAware and SetProcessDPIAwareness. Alternatively you can also define DPI-awareness in the application manifest, which is probably the preferable way to go. The difference between SetProcessDPIAware (1) and SetProcessDPIAwareness (2) are (among others):
  • (1) is available since Windows Vista, while (2) is available since Windows 8.1
  • (1) only supports a systemwide DPI setting (SYSTEM_DPI_AWARE), while PER_MONITOR DPI awareness was added with (2) in Windows 8.1. This allows to combine a high-resolution monitor with a "normal"-resolution monitor and the application automatically scales according to the monitor you move it to.
Note that - if you use (1) or (2) your application will only work in (1) Vista+ or even only in (2) Windows 8.1+. You will want to load the DLL dynamically and test whether the function is available (DYLIBLOAD) to make your application work on older Windows Versions too (or don't use the functions at all and the manifest instead).

Unfortunately I can't tell you how to make the application itself DPI-aware (so that it scales). The only thing I've already done regarding DPI-awareness is calling the two methods (1) and (2) as described above dynamically in a C++ application to disable Windows's automatic scaling.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

St_W wrote:Note that - if you use (1) or (2) your application will only work in (1) Vista+ or even only in (2) Windows 8.1+. You will want to load the DLL dynamically and test whether the function is available (DYLIBLOAD) to make your application work on older Windows Versions too (or don't use the functions at all and the manifest instead).

Unfortunately I can't tell you how to make the application itself DPI-aware (so that it scales). The only thing I've already done regarding DPI-awareness is calling the two methods (1) and (2) as described above dynamically in a C++ application to disable Windows's automatic scaling.
Hi St_W and thanks for your reply!

Only Vista plus is a bit of a pain, huh? Do some that use Free BASIC still use OSs before Vista, or is that just me?

Can you use the manifest to make the application per monitor aware? If so, then I can tell the user how to apply High-DPI Awareness to their program, and allow this functionality for OSs below Vista as well, or is High-DPI Awareness only a newer thing?

As regards to your last point, I think I've seen something on the tutorial page about retrieving OS-created figures for re-scaled UI elements. If this is so, then I can create some default scaling method for the GUIWIN class and allow the programmer to call that method in the message loop (my inquiries about the WM_DPICHANGED notification message tie in with this).

Thanks again.
St_W
Posts: 1618
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: Object-Oriented GUI Library

Post by St_W »

datwill310 wrote:Only Vista plus is a bit of a pain, huh? Do some that use Free BASIC still use OSs before Vista, or is that just me?
Windows XP is probably still used by some users, but Windows versions >= Vista should be pretty much standard today. Note that all this can be avoided by loading the system library dynamically (and testing whether the functionality is available) or using a manifest instead.
datwill310 wrote:Can you use the manifest to make the application per monitor aware?
Yes, you can. Note that all this will just tell the OS that your application is aware; of course your application hast to implement it properly, too.
datwill310 wrote:If so, then I can tell the user how to apply High-DPI Awareness to their program, and allow this functionality for OSs below Vista as well, or is High-DPI Awareness only a newer thing?
Windows XP has only rudimentary high-DPI support and doesn't support DPI-awareness, but nobody would use a high-resolution monitor with Windows XP anyway (as it doesn't properly support it). Windows versions below XP basically don't support high-DPI settings at all.

Microsoft explains everything quite well on MSDN: https://msdn.microsoft.com/en-us/librar ... 69266.aspx

That's basically all I know about this topic, but there are lots of useful resources on MSDN and other sites on the web about this.

To test your implementation properly you'll need Windows 8.1 or higher. And a multi-monitor setup with one high-resolution monitor would be also beneficial.
PaulSquires
Posts: 999
Joined: Jul 14, 2005 23:41

Re: Object-Oriented GUI Library

Post by PaulSquires »

I think that St_W has explained this very well. Jose Roca has already created a high-dpi aware class for creating Windows applications. It is called CWindow and is available over on my forum http://www.planetsquires.com/protect/forum/index.php I encourage you to download that class and see how Jose has implemented high-dpi awareness. In this day of huge monitors with incredible resolutions, not having your class high-dpi enabled will put your library at a disadvantage. I hope that you will be able to make it work because you seem to have put a lot of effort into your library.
Good luck!
PaulSquires
Posts: 999
Joined: Jul 14, 2005 23:41

Re: Object-Oriented GUI Library

Post by PaulSquires »

I will also add that it took me a long time to fully appreciate the need to have high-dpi support. It was not until I started seeing users use settings other than the standard 96 DPI Windows setting that it became truly clear why you need that functionality. There were lots of places in my code where I would add a few pixels here and there say for example to create a little spacing between controls. Well, that would totally screw up the layouts when used at different DPI settings. Those ordinal calculations need to be scaled so 5 pixels could actually be 8 or 10, etc at higher DPI's.

For example, instead of:
nSpacing = nWdith + 5

You would do this:
nSpacing = nWidth + ScaleX(5)

Once you get into the habit of doing it, it is no different than any other gotcha that you need to look out for.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

I'm sorry I couldn't get to you sooner, apparently this forum decided to not update me with what's going on anymore :|...
St_W wrote:Windows XP is probably still used by some users, but Windows versions >= Vista should be pretty much standard today. Note that all this can be avoided by loading the system library dynamically (and testing whether the functionality is available) or using a manifest instead.
I think I'll go with the manifest option, to enable High-API awareness anyway.
St_W wrote:Windows XP has only rudimentary high-DPI support and doesn't support DPI-awareness, but nobody would use a high-resolution monitor with Windows XP anyway (as it doesn't properly support it). Windows versions below XP basically don't support high-DPI settings at all.

Microsoft explains everything quite well on MSDN: https://msdn.microsoft.com/en-us/librar ... 69266.aspx

...

To test your implementation properly you'll need Windows 8.1 or higher. And a multi-monitor setup with one high-resolution monitor would be also beneficial.
I see. I barely remember the days when we used to have a PC running XP because I was too young XD. I can test for it properly since I have Windows 10. And thanks for the reference.
PaulSquires wrote:Jose Roca has already created a high-dpi aware class for creating Windows applications. It is called CWindow and is available over on my forum http://www.planetsquires.com/protect/forum/index.php I encourage you to download that class and see how Jose has implemented high-dpi awareness. In this day of huge monitors with incredible resolutions, not having your class high-dpi enabled will put your library at a disadvantage. I hope that you will be able to make it work because you seem to have put a lot of effort into your library.
Good luck!
I understand, and thanks for the reference: will look into it!
PaulSquires wrote:I will also add that it took me a long time to fully appreciate the need to have high-dpi support. It was not until I started seeing users use settings other than the standard 96 DPI Windows setting that it became truly clear why you need that functionality. There were lots of places in my code where I would add a few pixels here and there say for example to create a little spacing between controls. Well, that would totally screw up the layouts when used at different DPI settings. Those ordinal calculations need to be scaled so 5 pixels could actually be 8 or 10, etc at higher DPI's.

For example, instead of:
nSpacing = nWdith + 5

You would do this:
nSpacing = nWidth + ScaleX(5)

Once you get into the habit of doing it, it is no different than any other gotcha that you need to look out for.
I was thinking more of a single function to handle all windows within a GUIWIN object:

Code: Select all

do
	...
	win.scaleui() 'or something
	...
loop ...
Is this a reasonable method, or is it prefered to handle UI elements individually? Either way, I guess I will still be using your method XD.

Thanks again.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: Object-Oriented GUI Library

Post by datwill310 »

Hmm... I'm realising a few issues about this... Please hear me out.

First off, I can't test DPI-Awareness very effectively AT ALL. I only have one monitor, so I can't test for multi-monitor situations. Also my debug program (or ANY of the programs and extensions I have been running, including actual Windows apps, professional 3rd-party apps, and extensions, both professional and nonprofessional) did NOT respond to dynamic DPI changes. Settings actually says: "Some apps won't respond to scaling changes until you sign out." In fact, the ONLY app that DID respond to dynamic changes was the settings app. Everything else did not dynamically respond to changes. But when I signed out and re-opened my apps and stuff, EVERYTHING was fine, no blurry fonts or controls. EVEN the debug program was fine (I have created a manifest with the aid of the MSDN which hopefully enabled high-dpi awareness, which I tested and it does seem to work, see below).

This all tells me that, if it is important, absolutely critical for applications to respond to DPI-changes dynamically, then the apps I had been running WILL have responded, but they DID NOT.

Also, if you were to change your DPI setting, you'd probably have to close everything down and restart anyway? I mean, it's not like people are constantly changing the DPI all the time: they would set it once to the scaling they needed, and leave it alone.

Which leads me to say that this is something I cannot incorporate into the OGL, simply because I can't. Let me explain:

The page here tells of four basic steps:
MSDN wrote:Supporting Dynamic DPI Changes

You must perform the following steps to make your application per monitor-DPI aware:
1. Set the DPI awareness level
2. Get the DPI for the current monitor
3. Listen for DPI changes
4. Respond to changes
1. Setting DPI awareness.
This is best done through the manifest file of an application. Setting it through a function has disadvantages (?). Therefore, this is something that cannot be part of the OGL simply because you can't put a manifest file into the OGL.

2. Getting DPI for current monitor.
I am incorporating this functionality through the following functions (there is also a function to retrieve the monitor handle of primary, secondary monitor etc.):

Code: Select all

'monitor is a function which retrieves a monitor's handle. The default is the primary monitor
function monitordpix(byval m as HMONITOR = monitor) as ulong
		dim as ulong mx, my
		dim as any ptr dll = dylibload("shcore.dll")
		if dll <> NULL then
			dim dpi as function (as HMONITOR, as uinteger, as UINT ptr, as UINT ptr) as HRESULT
			dpi = dylibsymbol(dll, "GetDpiForMonitor")
			if dpi <> NULL then dpi(m, 0, @mx, @my) 'effective dpi
			dylibfree(dll)
		endif
		return mx
	end function
	function monitordpiy(byval m as HMONITOR = monitor) as ulong
		dim as ulong mx, my
		dim as any ptr dll = dylibload("shcore.dll")
		if dll <> NULL then
			dim dpi as function (as HMONITOR, as uinteger, as UINT ptr, as UINT ptr) as HRESULT
			dpi = dylibsymbol(dll, "GetDpiForMonitor")
			if dpi <> NULL then dpi(m, 0, @mx, @my) 'effective dpi
			dylibfree(dll)
		endif
		return my
	end function
3. Listening to DPI changes.
Now I get it: in order to dynamically respond to DPI changes, one must use WM_DPICHANGED, or do they? Does that message only respond if a window has been moved to another monitor with another DPI setting? Well, screw that, since I don't have two monitors to test with (or could any of you guys help me out with this?).

How does one listen for dynamic changing of the DPI setting? If I had this knowledge, then I could think about responding to dynamic changes of the DPI setting. But as it stands now, it appears that... I don't know how to do it...

4. Respond to changes.
Then I just thought...

Do I have to add scaling methods?

I mean, I've taken a look at CWindow.inc. As far as I'm aware, all the scaling properties are doing is multiplying the x and y coordinates of a control by a specified value. Do I have to add special methods for this, or can the programmer just do it himself/herself? Not to demine José Roca or his work or anything of the sort. It's great! Just that I personally do not see the need to incorporate this:

Code: Select all

x * scaling
y * scaling
when the programmer can simply create their own section or procedure dealing with this issue.

I will still be adding things like monitor handle, dimension, and dpi retrieval.

As for images and fonts, the programmer can easily change the logical widths and heights of the fonts and use separate images for each scaling setting. The OGL itself cannot do this easily, especially the images problem, since the OGL does not know what stored image is the scaled one you want for a particular DPI setting, does it? And if I somehow incorporate this logic into the OGL, it will make things more complex than it needs to be! Well, definitely more complex than this:

Code: Select all

win.image(ci) = imgindex
'imgindex is index of image which corresponds with the scaled version of the original image
Something else to consider is that some programmers may want to have more control over scaling. Then, writing a scaling method or methods may not be helpful to them.

===============================

In order to incorporate High-DPI awareness into your program, you have to write the correct manifest. That is it. If someone were to change the DPI setting dynamically, then they just have to sign out and back in again, there's nothing much I can do about that.

In other words, if you write the real manifest, you've done it. In order for the program to respond to the changes, you have to sign out and in.

Now, OGL didn't do any of that, did it?... It was the manifest.

This is why I am saying I can't exactly incorporate this feature into the OGL. I can certainly help by providing DPI retrieval functions etc., but to actually handle dynamic changes, the programmer has to do it from scratch.

Overall, while I appreciate the need for DPI-awareness, creating methods to perform a few multiplication sums is a bit, meh... Idk...
Post Reply