I'm wondering if this could be somewhat possible.
It would involve hacking and patching VB6 (hopefully just in memory so the runtime DLLs do not need to be touched on disk).
This question is intended to the ones that have knowledge exploring the VB6 internals (The Trick, wqweto...).
The idea is that VB6 already uses Single types for al twips based properties, but the "only" problem is that the twips-per-pixel calculation is somewhere rounded to integers.
This, as we all know, cause problems is some DPI settings, that are used more and more as time goes on. And if ultra-hight DPI monitors become common, at some point it will be a major issue for VB6 programs. And it will most probably happen, the only question is when.
The idea of the question is if it could be feasible to find where this rounding occurs and correct it (surely in more than one place, but probably not many).
I suspect that Currency is used in OLE's "metrics" calculations internally. You can see this abstraction "leak" by examining the data type used for IFont.Size for example.
Single type for many properties might even be just a holdover from earlier versions of VB written for Windows 3.x.
This TwipsPerPixel nonsense is one of the reasons I'm glad I don't work in VB6 anymore. I've always hated this Twips concept passionately. Why couldn't we just use pixel measurements like Win32 and just about everything else.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
This, as we all know, cause problems is some DPI settings, that are used more and more as time goes on. And if ultra-hight DPI monitors become common, at some point it will be a major issue for VB6 programs. And it will most probably happen, the only question is when.
Can you enlighten me on what problems you get. I agree its a case of when, but I'm not sure i've actually seen a vb6 app on a high dpi device.
Last time I delved into it the TwipsPerPixelX propertiy was retrieved from an internal structure and the value in this struct was a 32-bit integer which I tried to convert to 32-bit float by patching the fetching instructions but didn't succeed and it all seemed like a lost cause.
Probably The Trick has the powers to fix it but it's quite complicated as this DISPLAY (or was it DESKTOP?) structure is probably directly accessed from many functions inside the runtime.
First, and most important, the suggestion I made in the OP:
Originally Posted by wqweto
Last time I delved into it the TwipsPerPixelX propertiy was retrieved from an internal structure and the value in this struct was a 32-bit integer which I tried to convert to 32-bit float by patching the fetching instructions but didn't succeed and it all seemed like a lost cause.
Probably The Trick has the powers to fix it but it's quite complicated as this DISPLAY (or was it DESKTOP?) structure is probably directly accessed from many functions inside the runtime.
cheers,
</wqw>
Glad to know that at least someone tried.
OK, then it seems it is not easy.
Second topic: possible workarounds:
I spent some days fixing this issue in a large program, it has like 100 forms, and more than 100K LOC, with several UserControls.
I wasn't as difficult as I thought. This is my experience:
Intrinsic controls have no problem, only non-intrinsic control have. In my case they were MSHFlexGrids, RichTextBoxes and UserControls from the project itself and from a component that I have.
(note: that I have the program manifested for DPIAware, if you don't have the program manifested DPIAware, everything is scaled automatically... and blurred. If you have no manifest for DPI awareness then you can manifest for GDIScaling, that improves the things a bit - compared to unaware-)
At the start of the program I set a variable, in the Sub Main:
Code:
Private Declare Function GetDC Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long, ByVal nIndex As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hDC As Long) As Long
Public gDPIF as Single
Public Sub Main()
gDPIf = GetTrueTwipsPerPixelX / Screen.TwipsPerPixelX
End Sub
Private Function GetTrueTwipsPerPixelX() As Single
Dim h As Long
Const LOGPIXELSX As Long = 88
h = GetDC(0)
If h <> 0 Then
GetTrueTwipsPerPixelX = 1440 / GetDeviceCaps(h, LOGPIXELSX)
ReleaseDC 0, h
Else
GetTrueTwipsPerPixelX = Screen.TwipsPerPixelX
End If
End Function
Then, in the forms that a non-intrinsic control needs to fill a space, replace code (for example) from:
Code:
Public Sub Form_Resize()
' grdResults is a flex grid
grdResults.Move 60, 60, Me.ScaleWidth - 120, Me.ScaleHeight - 120
End Sub
to:
Code:
Public Sub Form_Resize()
grdResults.Move 60, 60, Me.ScaleWidth * gDPIf - 120, Me.ScaleHeight * gDPIf - 120
End Sub
The controls that are not placed by code (just set their location at design time) do not need this adjustment.
Form the controls that do not need to fill a certain space, such as buttons, I didn't see a problem, at least noticeable. Most of them probably I had no sizing code at run time.
For the controls that size themselves, as toolbars, there is no need to add code either.
Also, when other controls take their size or positions from corrected controls, the scale needs to be set back like ....Top = grdResults.Height / gDPIf
So... it was easier than I thought. In around three days I finished.
I still did not test much, but all other things seems to work.
For making this fix, I set Windows 10 to a custom scale of 130% (I use 125% normally). It gives a TwipsPerPixels of 11.52.
As a side note, I used my Project Examiner to find what forms had certain controls (MSHFlexGrid, RichTextBox).
Other possible workaround:
I had the idea of checking at the start of the program is GetTrueTwipsPerPixelX is integer or not, and if not to shell another version of the program and exit.
This secondversion is almost exactly the same, but whithout this check and with a manifest for GDIScaling.
It would be a bit cumbersome because it would require to make two exe compilations for each release.
When the problem arises:
Originally Posted by rjsnipe
I'm not sure i've actually seen a vb6 app on a high dpi device.
It is quite easy to see the problem, you do not need a ultra high-DPI monitor, just set the screen to 200% DPI (right click on the desktop, Display settings, set a custom scale).
This produces a TwipsPerPixels of 7.5.
100% --> 96 DPI
200% --> 192 DPI
1440/192 = 7.5 TwipsPerPixels
Or, if it is too big for your monitor, set it to 130%, it produces 11.52 TwipsPerPixels.
Twips/Pixels, DPI awareness:
Originally Posted by Niya
This TwipsPerPixel nonsense is one of the reasons I'm glad I don't work in VB6 anymore. I've always hated this Twips concept passionately. Why couldn't we just use pixel measurements like Win32 and just about everything else.
I used to dislike it too, but was when it didn't understand what the heck was that thing of "twips" and why they used that numbering that seemed arbitrary and not related to the real things that were pixels.
Until I needed to make the program DPI aware and understood the advantages.
VB6 is almost DPI aware by default... if you use twips.
OK, this topic would require to write a lot. May be if you are interested.
PS: in that regard (DPI independence) VB6 was quite advanced, better than other languagues (even newer ones).
I have no idea how .Net handles DPI independence if it works in pixels.
Last edited by Eduardo-; Jan 18th, 2021 at 08:33 PM.
For the ones that don't know about this problem, I'm attaching a test project to check it.
This project simply adjust the size of a RichTextBox to the form client area.
The code is:
Code:
Private Sub Form_Resize()
RichTextBox1.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight
End Sub
Compile the project and run the exe on different DPI settings (close and run the exe again on each setting).
For 100%, 125% and 150% there is no problem.
But for 200% there is, you will see that the RichTextBox does not fill the form.
200% makes the screen too small, so alternatively you can set a custom scale to 120% or 130%.
Side note:
In the test project I'm including a generic manifest for DPI awareness in the resource file. For final projects, if you want to avoid dilettante's concerns/complaints/scolding/critics, please use the actual program name.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
There is no problem to fix Screen's properties but it's quite difficult to change all the internal structures. Just for information, this is the places where TwipsPerPixels is used:
There is no problem to patch them all but different runtime builds has its own addresses. BTW this is the initialization procedure which initializes twips etc:
Then you end up with defining your own kind of twips based on the current resolution and the DPI%?
And do all drawing yourself. Like Olaf proposed with his Cairo libraries?
but different runtime builds has its own addresses.
Thank you very much for looking into this issue.
I forgot that there are different versions. I guess if at some point you could make a fix to patch the Dlls, it should be for SP6. But for the run-time will be a problem because I think there are more than one version on the end-user machines. And still MS could issue some modifications in the future (if they need to issue a security fix).
So, considering that, I think that adds lot of difficulty and possible problems.
Originally Posted by Arnoutdv
Then you end up with defining your own kind of twips based on the current resolution and the DPI%?
And do all drawing yourself.
I'm not sure to who this question is addressed and what you are asking.
Twips are twips and TwipsPerPixel by definition depend on the DPI setting.
Please take a look to this explanation about twips, DPI settings, and this topic.
As a result of my participation in the other thread where I was researching DPI, I decided to tackle this and see what's up while all this DPI stuff is still fresh in my mind. First I want to address this:-
That calculation is wrong. The correct way to calculate the DPI for 175% scaling is 1.75 * 96, which is equal to 168. You can confirm this with the GetDpiForWindow Win32 function.
With that out of the way lets move on to that little project you posted. I played with it for a bit before I reached the conclusion that the problem has absolutely nothing to do with how VB6 deals with twips. The problem lies with how VB6 performs the layout for specific controls. Somewhere inside the internals of VB6, the RichTextBox isn't correctly accepting the size values when it's at 175% scaling. If you replaced the RichTextBox with a normal multi-line TextBox, you'd see that it works perfectly at 175% scaling. What's more is that you will see that it will work correctly regardless of the Form's ScaleMode setting, even when it's set to vbPixels. Twips have no part at all to play in this problem. The fault is with the RichTextBox itself.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Turns out I was correct. The problem has nothing to do with Twips. Use this:-
vb6 Code:
Option Explicit
Private Declare Function GetDpiForWindow Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
' SetWindowPos Flags
Const SWP_NOSIZE = &H1
Const SWP_NOMOVE = &H2
Const SWP_NOZORDER = &H4
Const SWP_NOREDRAW = &H8
Const SWP_NOACTIVATE = &H10
Const SWP_FRAMECHANGED = &H20 ' The frame changed: send WM_NCCALCSIZE
Const SWP_SHOWWINDOW = &H40
Const SWP_HIDEWINDOW = &H80
Const SWP_NOCOPYBITS = &H100
Const SWP_NOOWNERZORDER = &H200 ' Don't do owner Z ordering
Instead of using the RichTextBox's Move method, I used the Win32 API SetWindowPos and it now works at 175% scaling and it doesn't matter what the Form's ScaleMode is. It works, even when the Form's ScaleMode is set to vbPixels. Turns out, we don't even need to deal with all that TwipsPerPixel mess to get this to work correctly for different DPIs. Plain old pixels are enough.
EDIT:
I also tested positioning the RichTextBox using the plain old Left/Top/Width/Height properties and that didn't work either. I can only conclude that there is a problem deep in the VB6 infrastructure that is just not capable of dealing with higher DPIs when positioning certain Controls. Best to stick with SetWindowPos to move and size controls in your DPI aware applications.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Best to stick with SetWindowPos to move and size controls in your DPI aware applications.
SetWindowPos works but ScaleX/Y fail when actual TwipsPerPixelX/Y are not integer values in 175% scaling.
Even if Form's ScaleMode is pixels the initial control position (in pixels) is scaled with 175% scaling as if the coordinates are persisted in twips (indeed they are).
SetWindowPos works but ScaleX/Y fail when actual TwipsPerPixelX/Y are not integer values in 175% scaling.
Even if Form's ScaleMode is pixels the initial control position (in pixels) is scaled with 175% scaling as if the coordinates are persisted in twips (indeed they are).
cheers,
</wqw>
SetWindowPos works exclusively in pixels. The only reason I'm using ScaleX/Y is because I'm reading the dimensions of the client area from ScaleWidth/ScaleHeight properties of the Form and I need them to be in pixels so it's necessary to convert them if the ScaleMode is not in pixels. You can cut out the need for ScaleX/Y entirely by using the GetClientRect API to get the dimensions of the client area. The net of it is that you can get the correct behavior without any concern for Twips or the ScaleMode or any of that.
Even so, the current code works correctly for me at 175% for me regardless of the ScaleMode setting.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
I have no idea what you are testing here but if you change RTB to a custom VB6 created UserControl (with a blue background for instance) and try to span it with Move 0, 0, Me.ScaleWidth, Me.ScaleHeight or SetWindowPos you will see the obvious failure in 175%.
I have no idea what you are testing here but if you change RTB to a custom VB6 created UserControl (with a blue background for instance) and try to span it with Move 0, 0, Me.ScaleWidth, Me.ScaleHeight or SetWindowPos you will see the obvious failure in 175%.
cgeers,
</wqw>
I just tested this and it still didn't fail, even with a UserControl. If it's failing for you, I might be missing something. I've attached the project I used to test it.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
I just tested this and it still didn't fail, even with a UserControl. If it's failing for you, I might be missing something.
Yes, must be the Move method that fails only and if the UserControl is Windowless=True the SetWindowPos hack is impossible.
Also if you set Align property so that the parent form repositions the control, this fails no matter if windowless or not.
If the UserControl is Container=True more oddities follow with contained controls, though I cannot simulate it. Probably some combination of ClipBehavior/ClipControls etc. settings on parent Form and UserControl.
I'm using IOleInPlaceObject::SetObjectRects to fix Move method in HighDPI modes like this:
Code:
Public Sub SyncObjectRectsToContainer(oCtl As IUnknown)
Const FUNC_NAME As String = "SyncObjectRectsToContainer"
Dim pOleObject As IOleObject
Dim pOleInPlaceObject As IOleInPlaceObject
Dim pOleInPlaceSite As IOleInPlaceSite
Dim uPosRect As RECT
Dim uClipRect As RECT
Dim uFrameInfo As OLEINPLACEFRAMEINFO
If Not oCtl Is Nothing Then
If TypeOf oCtl Is VBOleGuids3.IOleObject Then
Set pOleObject = oCtl
Set pOleInPlaceObject = oCtl
If pOleObject.GetClientSite(pOleInPlaceSite) = S_OK And Not pOleInPlaceSite Is Nothing Then
pOleInPlaceSite.GetWindowContext Nothing, Nothing, VarPtr(uPosRect), VarPtr(uClipRect), VarPtr(uFrameInfo)
pOleInPlaceObject.SetObjectRects VarPtr(uPosRect), VarPtr(uClipRect)
End If
End If
End If
Exit Sub
EH:
End Sub
I just call SyncObjectRectsToContainer after each Move to be sure. This fix was shared by a member of the forums here -- The Trick or LaVolpe, don't remember exactly.
Ehh....well I expect there are all kinds of gremlins waiting in the dark with this. I don't know enough to cover all the edge cases that would cause it to fail. I certainly don't know enough to have come up with something like that SyncObjectRectsToContainer function.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
That calculation is wrong. The correct way to calculate the DPI for 175% scaling is 1.75 * 96, which is equal to 168.
Yes, I made a mistake when I wrote the post, it is 96 / 100 and not 100 / 96.
Sorry, but you didn't discover pawder, you just discovered a typing mistake.
Originally Posted by Niya
With that out of the way lets move on to that little project you posted. I played with it for a bit before I reached the conclusion that the problem has absolutely nothing to do with how VB6 deals with twips. The problem lies with how VB6 performs the layout for specific controls. Somewhere inside the internals of VB6, the RichTextBox isn't correctly accepting the size values when it's at 175% scaling. If you replaced the RichTextBox with a normal multi-line TextBox, you'd see that it works perfectly at 175% scaling. What's more is that you will see that it will work correctly regardless of the Form's ScaleMode setting, even when it's set to vbPixels. Twips have no part at all to play in this problem. The fault is with the RichTextBox itself.
If you had read the OP and the thread, that was already covered. Intrinsic controls don't have this problem. You didn't discover anything once more.
Of course using API to position controls is an alternative solution. But IMO it is easier what I suggested above.
We are not taking about fixing one control, but a whole large project. The RichTextBox was just an example for the ones that were not aware of this issue.
If you had read the OP and the thread, that was already covered. Intrinsic controls don't have this problem. You didn't discover anything once more.
You guys were focused on twips when that had nothing to do with it. All I showed was that in the case of the sample you posted, you could induce the correct behavior whether or not twips were involved in any way.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
You guys were focused on twips when that had nothing to do with it. All I showed was that in the case of the sample you posted, you could induce the correct behavior whether or not twips were involved in any way.
If you mean your solution of using API everywere to position controls, it is a solution but not the best one.
But if you say that for the other approaches internal TwipsPerPixels has nothing to do, you are wrong and totally ignorant of this issue.
If you mean your solution of using API everywere to position controls, it is a solution but not the best one.
But if you say that for the other approaches internal TwipsPerPixels has nothing to do, you are wrong and totally ignorant of this issue.
You're the one that's being ignorant here. What you are completely failing to grasp is that all these common controls and the Forms themselves are built on top of operating system abstractions. Every time you access the hwnd and hdc properties of Forms, UserControls and common controls, you are accessing operating system resources that has nothing to do with VB6. VB6's ThunderForm and UserControl classes are wrappers around these OS objects and it is these wrappers that implement all this TwipsPerPixel stuff. The OS doesn't know anything about twips as far as it's controls and top level windows are concerned. The Windows operating system measures and positions everything that has an hwnd according to pixel measuremeants, not twips. The bottom line is, whether you use twips or you develop your own system of device independent co-ordinates, at some point you are going to have to tell Windows what to do and you're going to have to do it in pixels. Do you even know how VB6 creates a Form? I'll tell you, it calls this Win32 API function named CreateWindow. That function has several variations and has undergone several changes over the years but it's ultimately what is being called to create every control and every Form in VB6. Do you see anything about twips there? No, it's measured in device units which is basically saying it's expecting sizes and positions to be expressed as pixels.
Working with twips is a choice, not a necessity. You could use twips, you could use pixels and if they don't meet your needs, you can develop your own device independent unit like DirectX does with DIPs or whatever units WPF uses internally. Point is, all this effort trying to hack twips in VB6 for this DPI stuff shows a seriously lack of understanding of what is actually happening under the hood. Let me say this clearly so you can understand. Twips are just an abstract concept meant to facilitate conversions between different co-ordinate systems. That's all it is. It is not the be all end all of anything.
I think you're letting the fact that I didn't know about writing DPI aware applications until recently go to your head. I never knew about it because I've never needed to. But make no mistake, I have a lot of experience dealing with this kind of stuff. I've written game engines, I've written all manner of controls. I've done all kinds of wacky things involving different kinds of windows(eg. Layered windows) and graphics. I'm not trying to boast or belittle but I'm letting you know that I know what the hell I'm talking about. I've spent countless hours over many many years learning how a lot of this stuff works. Now I'm not gonna lie, I'm no where near as good as people like Olaf, Tanner Helland, wqweto or LaVolpe but I can hold my own pretty decently. I had my time in the trenches. It took me all of 20 minutes to solve that problem in the project you posted. I know it's not a complete solution and it would probably break under a lot of different conditions but I did that even while not having not used VB6 for something like 6 years and never even knowing a problem like that existed before that day. So don't talk about what I'm ignorant of.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
What you are completely failing to grasp is that all these common controls and the Forms themselves are built on top of operating system abstractions. Every time you access the hwnd and hdc properties of Forms, UserControls and common controls, you are accessing operating system resources that has nothing to do with VB6. VB6's ThunderForm and UserControl classes are wrappers around these OS objects and it is these wrappers that implement all this TwipsPerPixel stuff. The OS doesn't know anything about twips as far as it's controls and top level windows are concerned. The Windows operating system measures and positions everything that has an hwnd according to pixel measuremeants, not twips. The bottom line is, whether you use twips or you develop your own system of device independent co-ordinates, at some point you are going to have to tell Windows what to do and you're going to have to do it in pixels. Do you even know how VB6 creates a Form? I'll tell you, it calls this Win32 API function named CreateWindow. That function has several variations and has undergone several changes over the years but it's ultimately what is being called to create every control and every Form in VB6. Do you see anything about twips there? No, it's measured in device units which is basically saying it's expecting sizes and positions to be expressed as pixels.
LOL. That's a quite basic stuff that most people here already know.
When I said ignorant I wasn't talking about that.
I took for granted that you knew all that.
If I thought that you didn't know that, I would not try to explain anything about this problem.
I see you have a tendency to answer to things you don't understand. And with arrogance. Ignorance is arrogant.
That's because even if you work in pixels, VB6 works in twips internally.
Originally Posted by Niya
, not a necessity.
It is a necessity for making the program DPI aware.
Well, you could do all the calculations for your own in pixels, but that would complicate things a lot.
Originally Posted by Niya
You could use twips, you could use pixels and if they don't meet your needs, you can develop your own device independent unit like DirectX does with DIPs or whatever units WPF uses internally.
For most objects like forms and UserControls you can use a custom scale, you just need to set the scale with ScaleLeft, ScaleTop, ScaleWidth and ScaleHeight, or use the Scale method for all four at a time (and I'm the ignorant).
But not for every control. Some work only in twips and there is no choice.
Originally Posted by Niya
Point is, all this effort trying to hack twips in VB6 for this DPI stuff shows a seriously lack of understanding of what is actually happening under the hood.
Of you.
Originally Posted by Niya
Let me say this clearly so you can understand. Twips are just an abstract concept meant to facilitate conversions between different co-ordinate systems.
It can be abstract or concrete, it depends how you want to see these things.
It is concrete because it is one logical inch / 1440... or abstract, whatever you want, it is semantic.
Originally Posted by Niya
That's all it is. It is not the be all end all of anything.
Not, it is just a bug in VB6. Or a design feature that is now is obsolete and causing problems. And it will cause more problems in the future as some DPI settings (like 200%) become more common.
You didn't understand the problem so far, but right now I'm too tired to explain it to you (I already did with the DPI aware topic and see how you pay back). Perhaps someone else has more desire to explain things to an arrogant guy like you.
Originally Posted by Niya
I think you're letting the fact that I didn't know about writing DPI aware applications until recently go to your head.
It is only one day that you gained some clues about what DPI aware is (because I had to taught to you because you were unable to study the subject for yourself), and you are telling me that I don't understand it, when I had done DPI aware apps for years. Even per monitor.
You are a clinical case.
Originally Posted by Niya
I never knew about it because I've never needed to.
I needed it since many years ago, this problem is not new. It started with Windows Vista.
In fact, the problem was present from the start, from when Windows allowed to change the DPI setting from 96 to something else. But with old monitors and Windows it didn't appear too frequently. But I already explained all that to you.
VB6 was quite ready from the beginning to face this problem of different DPI settings.
Originally Posted by Niya
But make no mistake, I have a lot of experience dealing with this kind of stuff. I've written game engines, I've written all manner of controls. I've done all kinds of wacky things involving different kinds of windows(eg. Layered windows) and graphics. I'm not trying to boast or belittle but I'm letting you know that I know what the hell I'm talking about.
I've spent countless hours over many many years learning how a lot of this stuff works. Now I'm not gonna lie, I'm no where near as good as people like Olaf, Tanner Helland, wqweto or LaVolpe but I can hold my own pretty decently. I had my time in the trenches. It took me all of 20 minutes to solve that problem in the project you posted. I know it's not a complete solution and it would probably break under a lot of different conditions but I did that even while not having not used VB6 for something like 6 years and never even knowing a problem like that existed before that day. So don't talk about what I'm ignorant of.
You proposed a third solution that is to position the controls with API. that's an alternative.
But as I said, not a good one (at least for me).
Do I have to explain why it is not a good one? I don't feel like it.
This thread wasn't intended for people like you, but for people that already understand the problem and are able to intend a solution. They already answered (without asking about the problem because they already understand it).
They are The trick and wqweto.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
That's the point, you come to the forum for arguing, other people come to learn and share knowledge.
I don't have any interest in arguing with you, I don't want to convince you of anything.
It is the same problem, UserControls, Forms, all the same issue.
The positioning by API worked because two problems canceled each other: ScaleWidth/ScaleHeight were wrong, and ScaleX/ScaleY converted wrongly, and thus they canceled each other and returned the right pixels.
Most of VB6 still works because all is internally wrong but consistent, but the postioning of controls via .Move or .Left/Top/Width/Height unfortunately seems to be doing the conversion"right".
Last edited by Eduardo-; Jan 23rd, 2021 at 03:40 AM.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Was just a sample to show the problem.
Real programs has some forms with many controls that position in the available form space with much more complex calculations.
To move all that code to API based positioning would take much more work than the other option that is just to put a correction factor in the existing code in the places it is needed (what I did).
Also, as wqweto already mentioned, for windowless UserControls there is no API option.
Last edited by Shaggy Hiker; Jan 23rd, 2021 at 03:34 PM.
Reason: Removed inflammatory stuff.