Origin 0,0 (in)dependent from themes?

This forum is for eXpress++ general support.
Message
Author
daan_vossebeld
Posts: 11
Joined: Fri Jan 29, 2010 1:37 am

Origin 0,0 (in)dependent from themes?

#1 Post by daan_vossebeld »

I have an application where I fully control all the objects on pixel level. I am struggling however with the origin { 0,0 }position when working with different themes. In the attachments you can find code and the output for themes "Windows Classic" and "Windows Vista" of a test program that prints two pushbuttons. My practical experience is that with "non-Classic" themes I have to add about 7-9 pixels to the desired position. I see however no exact relation with the SM_CYCAPTION, SM_CYFRAME and SM_CYBORDER parameters of GetSystemMetrics (DLL).

My questions:
- Where is exactly the origin 0,0 in eXpress++?
- Is this a fixed point, derived from the "Windows Classic" theme?
- What is the formula to find the first "usable" pixel on the Y-axis?

Daan
Attachments
test1.zip
(466 Bytes) Downloaded 790 times
TestOrigin.jpg
TestOrigin.jpg (62.94 KiB) Viewed 16977 times

User avatar
Auge_Ohr
Posts: 1407
Joined: Wed Feb 24, 2010 3:44 pm

Re: Origin 0,0 (in)dependent from themes?

#2 Post by Auge_Ohr »

daan_vossebeld wrote:I have an application where I fully control all the objects on pixel level. I am struggling however with the origin { 0,0 }position when working with different themes. In the attachments you can find code and the output for themes "Windows Classic" and "Windows Vista" of a test program that prints two pushbuttons.
this is DWM (Desktop Windows Manager) "Border Padding"

try this DWM Code on Vista(?)/Win7

Code: Select all

#include "DLL.CH"
#include "GRA.CH"
#include "XBP.CH"

DLLFUNCTION DwmExtendFrameIntoClientArea( nHWND, pMargins ) ;
  USING STDCALL                                             ;
  FROM  DWMAPI.DLL
DLLFUNCTION DwmIsCompositionEnabled( @nEnabled )            ;
  USING STDCALL                                             ;
  FROM  DWMAPI.DLL

#define cxLeftWidth    0
#define cxRightWidth   4
#define cyTopHeight    8
#define cyBottomHeight 12

PROCEDURE Main()

LOCAL oDlg
LOCAL oTxt

   oDlg := VistaDialog():New( AppDesktop() )
   oDlg:Title     := "Vista Dialog with Glass"
   oDlg:TaskList  := .T.
   oDlg:PadLeft   := 5
   oDlg:PadRight  := 5
   oDlg:PadTop    := 5
   oDlg:PadBottom := 45
   oDlg:Visible   := .F.
   oDlg:Create( ,,, {400,200} )

   oTxt := XbpSLE():New( oDlg )
   oTxt:Create( ,, {10,5},{150,25} )
   oTxt:SetData( "Test Frame..." )

   CenterControl( oDlg )

   oDlg:ShowModal()

   oDlg:Destroy()

RETURN


CLASS VistaDialog FROM XbpDialog
EXPORTED:
   VAR    PadLeft
   VAR    PadRight
   VAR    PadBottom
   VAR    PadTop

   METHOD Init()
   METHOD Create()
ENDCLASS


METHOD VistaDialog:Init( oParent, oOwner, aPos, aSize, aPP, lVisible )

LOCAL nTmp := 0

   ::XbpDialog:Init( oParent, oOwner, aPos, aSize, aPP, lVisible )
   IF "Vista" $ OS()
      DwmIsCompositionEnabled( @nTmp )
      IF nTmp != 0
         ::SetColorBG( XBPSYSCLR_TRANSPARENT )
      ELSE
         ::SetColorBG( XBPSYSCLR_ACTIVETITLE )
      ENDIF
   ENDIF

   ::PadLeft   := 0
   ::PadTop    := 0
   ::PadRight  := 0
   ::PadBottom := 0

RETURN self


METHOD VistaDialog:Create( oParent, oOwner, aPos, aSize, aPP, lVisible )

LOCAL aRect
LOCAL cBin
LOCAL nTmp := 0

   IF ValType(lVisible) != "L"
      lVisible := ::Visible
   ENDIF

   ::XbpDialog:Create( oParent, oOwner, aPos, aSize, aPP, .F. )

   IF "Vista" $ Os()
      DwmIsCompositionEnabled( @nTmp )
      IF nTmp != 0
        cBin := L2Bin(::PadLeft)  + L2Bin(::PadTop) + ;
                L2Bin(::PadRight) + L2Bin(::PadBottom)
        DwmExtendFrameIntoClientArea( ::GetHWND(), @cBin )
      ENDIF
   ENDIF

   aRect := ::CurrentSize()
   aRect := {0,0,aRect[1],aRect[2]}
   aRect := ::CalcClientRect( aRect )
   aRect[1] += ::PadLeft
   aRect[2] += ::PadBottom
   aRect[3] -= (::PadRight + ::PadLeft)
   aRect[4] -= (::PadTop + ::PadBottom)

   ::DrawingArea:SetPosAndSize( {aRect[1],aRect[2]},{aRect[3],aRect[4]})

   IF lVisible == .T.
      ::Show()
   ENDIF

RETURN self
or you can use "ClientSize" at :create()
daan_vossebeld wrote:My practical experience is that with "non-Classic" themes I have to add about 7-9 pixels to the desired position. I see however no exact relation with the SM_CYCAPTION, SM_CYFRAME and SM_CYBORDER parameters of GetSystemMetrics (DLL).
there is a new Constante for Vista(?)/Win7

Code: Select all

#define SM_CXDLGFRAME            7
#define SM_CYDLGFRAME            8
#define SM_CYMENU               15
#define SM_CYCAPTION             4
#define SM_CXPADDEDBORDER       92

LOCAL nWidthBorder   := xbpGetSystemMetrics( SM_CXDLGFRAME )
LOCAL nHeightBorder  := xbpGetSystemMetrics( SM_CYDLGFRAME )
LOCAL nBorderPadding := 0   

IF OnOSversion() > 5                          // Vista-Win7 DVW Aero
   nBorderPadding := xbpGetSystemMetrics(SM_CXPADDEDBORDER)
ENDIF
...

FUNCTION xbpGetSystemMetrics( nValue )
RETURN DllCall( "USER32.DLL", DLL_STDCALL, "GetSystemMetrics", nValue )
more you find at http://msdn.microsoft.com/en-us/library ... 85%29.aspx
greetings by OHR
Jimmy

daan_vossebeld
Posts: 11
Joined: Fri Jan 29, 2010 1:37 am

Re: Origin 0,0 (in)dependent from themes?

#3 Post by daan_vossebeld »

Jimmy,

Thank you for your quick reaction.
I cannot use your first suggestion, because I fully work with eXpress commands. Further I know the new parameter (X-axis oriented) of your second suggestion. The returned value in Vista and XP for the themes "Windows Classic", "Windows Vista" and "Windows XP" are always 0.
Addition: My problem exists not only in Vista but also on XP with theme "Windows XP". In fact I am looking for the formula that calculates the topleft usable {n,0 } Y-axis setting.
Maybe Roger will also look to this.

Daan

User avatar
rdonnay
Site Admin
Posts: 4729
Joined: Wed Jan 27, 2010 6:58 pm
Location: Boise, Idaho USA
Contact:

Re: Origin 0,0 (in)dependent from themes?

#4 Post by rdonnay »

Due to the fact that the Windows coordinate system is reversed from the Xbase++ coordinate system, a coordinate of 0,0 must be recalculated based on the window height. Unfortunately, this calculation must also take into consideration the height of the title bar and and menu bar and that's what changes when you change themes.

When I originally wrote eXpress++, there was no ability to change themes under Win 98 so the title bar height and menu bar height was always constant. That has changed over the years, yet I have not done anything to compensate for it. I will make that fix in build 255. Nobody has ever asked for this so I have put it out of my mind. It requires making calls to the Windows API function GetSystemMetrics() to get the height of the title bar and the height of the menu bar.

The reason nobody has ever complained about this is because most eXpress++ users tend to use the FIT clause of DCREAD GUI. This causes the screen to automatically fit around the objects with a padding of 10 pixels. It makes all screens look good regardless of where your coordinates start.

You could try this:

DCGETOPTIONS FITPAD 0
DCREAD GUI FIT OPTIONS GetOptions

If that doesn't work for you, let me know which version of eXpress++ you are using and I will give you a workout (some changes to the code) that you can make until I release build 255.
The eXpress train is coming - and it has more cars.

daan_vossebeld
Posts: 11
Joined: Fri Jan 29, 2010 1:37 am

Re: Origin 0,0 (in)dependent from themes?

#5 Post by daan_vossebeld »

Roger,

On the Y-axis it works, but on the X-axis the FIT clause introduces new problems. In some situations the window becomes to wide. Because it has to do with the FIT clause, I can't influence this. I could not find another (new) workaround for this problem.
I hope you will make a structural solution, using more GetSystemMetrics data. In some important windows of my program where I control all objects on pixel level I don't want to use the FIT clause. In many other windows I am happy with the FIT clause.

Daan

daan_vossebeld
Posts: 11
Joined: Fri Jan 29, 2010 1:37 am

Re: Origin 0,0 (in)dependent from themes?

#6 Post by daan_vossebeld »

I am using Xbase 1.90.355 with eXpress 1.9.254.

User avatar
rdonnay
Site Admin
Posts: 4729
Joined: Wed Jan 27, 2010 6:58 pm
Location: Boise, Idaho USA
Contact:

Re: Origin 0,0 (in)dependent from themes?

#7 Post by rdonnay »

Here is a modified _dcgetbx.prg.

Copy it to your \exp19\source\dclipx folder and rebuild dclipx.dll by running build19.bat or build19_sl1.bat

The change was made to line 1674.

Let me know if that works for you or if there is any other modification required.
Attachments
_dcgetbx.zip
(77.87 KiB) Downloaded 775 times
The eXpress train is coming - and it has more cars.

daan_vossebeld
Posts: 11
Joined: Fri Jan 29, 2010 1:37 am

Re: Origin 0,0 (in)dependent from themes?

#8 Post by daan_vossebeld »

It did not directly work. I changed lines 1674-1676:
Old:
nStartRow := nParentHeight - nStartRow - ;
GetSystemMetrics(4) - GetSystemMetrics(15) - 8 - ;
aOptions[nGETOPT_ROWOFFSET]
New:
nStartRow := nParentHeight - nStartRow - ;
GetSystemMetrics(33) - GetSystemMetrics(4) - IIF(::isMenu,GetSystemMetrics(15),0) - 8 - ;
aOptions[nGETOPT_ROWOFFSET]

It works for theme "Windows Vista".
For the themes "Windows Classic" and "Windows XP" there are about 4-6 superfluous pixels between the menubar and the pushbuttons.
I think the "-8" in line 1675 was a fixed value for the GetSystemMetrics(33). But dropping the value gives also wrong results. Maybe you can explain this.

Daan

User avatar
Auge_Ohr
Posts: 1407
Joined: Wed Feb 24, 2010 3:44 pm

Re: Origin 0,0 (in)dependent from themes?

#9 Post by Auge_Ohr »

hi,
daan_vossebeld wrote:It did not directly work. I changed lines 1674-1676:

Code: Select all

GetSystemMetrics(33)
SM_CYSIZEFRAME = 33 ist incorrect !
daan_vossebeld wrote:It works for theme "Windows Vista".
For the themes "Windows Classic" and "Windows XP" there are about 4-6 superfluous pixels between the menubar and the pushbuttons.
this is "visual Style". use IsThemeActive()
daan_vossebeld wrote:I think the "-8" in line 1675 was a fixed value for the GetSystemMetrics(33). But dropping the value gives also wrong results. Maybe you can explain this.
GetSystemMetrics http://msdn.microsoft.com/en-us/library ... 85%29.aspx

Code: Select all

#define SM_CXDLGFRAME            7
#define SM_CYDLGFRAME            8
#define SM_CYMENU               15
#define SM_CYCAPTION             4
#define SM_CXPADDEDBORDER       92

LOCAL nHeightTitlebar     := xbpGetSystemMetrics( SM_CYCAPTION )
LOCAL nHeightMenubar      := xbpGetSystemMetrics( SM_CYMENU )
LOCAL nWidthBorder        := xbpGetSystemMetrics( SM_CXDLGFRAME )
LOCAL nHeightBorder       := xbpGetSystemMetrics( SM_CYDLGFRAME )
LOCAL nBorderPadding := 0

   IF OnOSVersion() > 5                          // Vista-Win7 DVW Aero
      nBorderPadding := xbpGetSystemMetrics(SM_CXPADDEDBORDER)
   ENDIF
   IF IsThemeActive() = .T.
      ....
   ENDIF
greetings by OHR
Jimmy

User avatar
rdonnay
Site Admin
Posts: 4729
Joined: Wed Jan 27, 2010 6:58 pm
Location: Boise, Idaho USA
Contact:

Re: Origin 0,0 (in)dependent from themes?

#10 Post by rdonnay »

Jimmy is correct.

The 8 pixels was to compensate for the border width.
I will read the metrics for the border width too.

I'll try to get you another update today.
The eXpress train is coming - and it has more cars.

Post Reply