Any guide on creating DPI-aware apps?

Any guide on creating DPI-aware apps?

Postby hua » Wed Nov 30, 2011 9:41 am

Hi guys,

Anyone has any tips, gotchas to share in regards of creating FWH apps that are dpi-aware?

I only realize the problem after a couple of our customers complained that they can't navigate to the end of my scrollable dialog. I've bookmarked http://msdn.microsoft.com/en-us/library ... 60(v=vs.85).aspx for reading later but for now I need to solve the scrollable dialog part first.

Using fwh\samples\testdscr_.prg, this is what I get after I changed to 120dpi and trying to navigate using the scrollbar to the bottom:
Image

This is what should be seen:
Image

So how should testdscr_.prg be modified to make it behave correctly irregardless what's the dpi (user can set the dpi to other than 96 or 120)?

TIA
FWH 11.08/FWH 19.12
BCC5.82/BCC7.3
xHarbour/Harbour
hua
 
Posts: 1072
Joined: Fri Oct 28, 2005 2:27 am

Re: Any guide on creating DPI-aware apps?

Postby hua » Wed Nov 30, 2011 9:50 am

Got another interface issue. When user run our program on a more recent notebook pre-installed with Win7, the placement of controls on dialogs went crazy.

After some googling I suspect this is due to Win7's so called dpi-virtualization.

Read something about preparing a manifest that tell Win7 that an exe is already dpi-aware so don't auto-scale it. Will let you guys know the outcome once I could get my hand on a Win7 notebook
FWH 11.08/FWH 19.12
BCC5.82/BCC7.3
xHarbour/Harbour
hua
 
Posts: 1072
Joined: Fri Oct 28, 2005 2:27 am

Re: Any guide on creating DPI-aware apps?

Postby Antonio Linares » Wed Nov 30, 2011 2:18 pm

Hua,

Thanks for your feedback! :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42085
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Any guide on creating DPI-aware apps?

Postby Antonio Linares » Wed Nov 30, 2011 2:30 pm

Hua,

Have you tried to automatically calculate it based on the oDlg:nHeight value ?

I think that in these lines:
Code: Select all  Expand view
  ACTIVATE DIALOG oDlg ;
      ON INIT ( oScrDlg := TScrDlg():New( oDlg, 1, 65, 1, 70), oDlg:SetSize( 560, 550 ), oDlg:Center() )
 

550 + 65 should be equal to oDlg:nHeight
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42085
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Any guide on creating DPI-aware apps?

Postby RAMESHBABU » Thu Dec 01, 2011 10:14 am

Hi,

Out of curiosity, I just tested TESTDSCR_.PRG.

I set the DPI to 120 and changed D_HEIGHT to 18 from 13

Code: Select all  Expand view

#define D_HEIGHT          18 //13
 


Then it worked perfectly.

To automatically calculate D_HEIGHT define, we need to know what is the current DPI Setting.
Based on that we can set the correct D_HEIGHT, which enables correct display of Scrollable Dialog.

Mr.Antonio,
Is there any such function to know the current DPI Setting ?

Regards,

- Ramesh Babu P
User avatar
RAMESHBABU
 
Posts: 624
Joined: Fri Oct 21, 2005 5:54 am
Location: Secunderabad (T.S), India

Re: Any guide on creating DPI-aware apps?

Postby Antonio Linares » Thu Dec 01, 2011 10:38 am

Ramesh,

http://msdn.microsoft.com/en-us/library/ms701681(v=vs.85).aspx

To get the system dpi setting, use the CDC::GetDeviceCaps function with the LOGPIXELSX flag. If you do not cancel dpi scaling, this call returns the default value of 96 dpi.


So it should be:

#define LOGPIXELSX 88

local hDC := GetDC( 0 )
MsgInfo( GetDeviceCaps( hDC, LOGPIXELSX ) )
ReleaseDC( 0, hDC )
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42085
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Any guide on creating DPI-aware apps?

Postby RAMESHBABU » Thu Dec 01, 2011 1:51 pm

Mr.Antonio,

Thanks for your valuable suggestion,

I have tested the following code not only with 96 and 120 DPIs but also with
various DPIs and found to be working well.

Image

Code: Select all  Expand view


// Testing how to scroll a dialog with its contents

#include "FiveWin.ch"

*#define d_width           4
*#define d_height         18

#define LOGPIXELSX        88

STATIC d_width := 4, d_height := 13

FUNCTION Main()

   LOCAL oDlg, oScrDlg

   local hDC  := GetDC( 0 )

   DEFINE DIALOG oDlg RESOURCE "dlgComScroll" ;  
         TITLE "Scroll dialog"            ;
         STYLE nOR( WS_VSCROLL, WS_HSCROLL )

   oDlg:bMouseWheel = { | nKey, nDelta, nXPos, nYPos | MouseWheel( nKey, nDelta, nXPos, nYPos, oScrDlg ) }

   ACTIVATE DIALOG oDlg ;
      ON INIT ( Set_D_Height(), oScrDlg := TScrDlg():New( oDlg, 1, 65, 1, 70), oDlg:SetSize( 560, 550 ), oDlg:Center() )

RETURN( NIL )



function MouseWheel( nKey, nDelta, nXPos, nYPos, oScrDlg )

   local oVScroll := oScrDlg:oDlg:oVScroll

   if nDelta < 0
      oVScroll:GoDown()
   else
      oVScroll:GoUp()
   endif      

   oScrDlg:VScroll()

return nil

//============================================================================
// FUNCTION : Set_D_Height()
// Purpose  : To Set new d_height for the Scroll bar
//============================================================================

PROCEDURE Set_D_Height()

LOCAL nDpi := GetCurrentDpi()

d_height := (nDpi * 13 / 96)

RETURN

//============================================================================
// FUNCTION : GetCurrentDpi()
// Purpose  : To Get the Windows Current DPI Setting
//============================================================================

FUNCTION GetCurrentDpi()

local hDc  := GetDc(0)
local nDpi := GetDeviceCaps( hDC, LOGPIXELSX )

nDpi := GetDeviceCaps( hDC, LOGPIXELSX )
MsgInfo( LTRIM(STR(nDpi))+" DPI" )

ReleaseDC( 0, hDC )

RETURN nDpi

//============================================================================
// FileName : SCROLL.PRG
// Purpose  :  dialog Scroll Class
// Author   : Eric Yang
// Update History :
//      Date     Contents
//    ---------- ---------------------------------------------------------------
//    1997.02.01
//    2006.29.12 By Rossini - Brasil
//============================================================================
#include "FiveWin.ch"

#ifndef TRUE
   #define TRUE              .T.
   #define FALSE             .F.
#endif

CLASS TScrDlg

   DATA oDlg
   DATA nVPos, nHPos

   METHOD New( oDlg,nV1,nV2,nH1,nH2 ) CONSTRUCTOR
   METHOD SetScroll( nV1,nV2,nH1,nH2 )

   //-*------------------------------------------------------------
   METHOD VScroll()
   METHOD VScrollThumb()
   METHOD VScrollTrack()
   METHOD VScrollPgDown()
   METHOD VScrollPgUp()

   //-*-----------------------------
   METHOD HScroll()
   METHOD HScrollThumb()
   METHOD HScrollTrack()
   METHOD HScrollPgDown()
   METHOD HScrollPgUp()

ENDCLASS

METHOD New( oDlg,nV1,nV2,nH1,nH2 ) CLASS TScrDlg
   ::nVPos := 0
   ::nHPos := 0
   ::oDlg  := oDlg
   ::SetScroll( nV1,nV2,nH1,nH2 )
RETURN Self

METHOD SetScroll( nV1,nV2,nH1,nH2 ) CLASS TScrDlg
LOCAL aCoors1:={},aCoors2:={}
   //--------------------------------------------------
   //-* Vertical Scroll Bar
   if ::oDlg:oVScroll != NIL
      ::oDlg:oVScroll:SetRange( nV1,nV2 )
      ::nVPos := ::oDlg:oVScroll:GetPos()
      ::oDlg:oVScroll:bGoDown   := {|| ::VScroll() }
      ::oDlg:oVScroll:bGoUp     := {|| ::VScroll() }
      ::oDlg:oVScroll:bPageUp   := {|| ::VScrollPgUp() }
      ::oDlg:oVScroll:bPageDown := {|| ::VScrollPgDown() }
      ::oDlg:oVScroll:bGoTop    := {|| ::VScroll() }
      ::oDlg:oVScroll:bGoBottom := {|| ::VScroll() }
      ::oDlg:oVScroll:nPgStep   := 10
      //::oDlg:oVScroll:lReDraw := TRUE
      ::oDlg:oVScroll:bPos      := {|nPos| ::VScrollThumb(nPos) }
      ::oDlg:oVScroll:bTrack    := {|nPos| ::VScrollTrack(nPos) }
   endif
   //--------------------------------------------------
   //-* Horizontal Scroll Bar
   if ::oDlg:oHScroll != NIL
      ::oDlg:oHScroll:SetRange( nH1,nH2 )
      ::nHPos := ::oDlg:oHScroll:GetPos()
      ::oDlg:oHScroll:bGoDown   := {|| ::HScroll() }
      ::oDlg:oHScroll:bGoUp     := {|| ::HScroll() }
      ::oDlg:oHScroll:bPageUp   := {|| ::HScrollPgUp() }
      ::oDlg:oHScroll:bPageDown := {|| ::HScrollPgDown() }
      ::oDlg:oHScroll:bGoTop    := {|| ::HScroll() }
      ::oDlg:oHScroll:bGoBottom := {|| ::HScroll() }
      ::oDlg:oHScroll:nPgStep   := 10
    //::oDlg:oHScroll:lReDraw   := TRUE
      ::oDlg:oHScroll:bPos      := {|nPos| ::HScrollThumb(nPos) }
      ::oDlg:oHScroll:bTrack    := {|nPos| ::HScrollTrack(nPos) }
   endif
*   ::oDlg:bKeyChar := {|nKey,nFlags| ScrollKey(nKey) }
   //--------------------------------------------------
RETURN( NIL )
/*
STATIC FUNCTION ScrollKey(nKey)

   MsgInfo( "Key : "+str(nKey,10) )

   //if nKey == K_ENTER
   //   goMainDlg:End()
   //   lRetVal := TRUE
   //endif
RETURN( NIL )
*/


//=================================================================
//-* Vertical Scroll Bar
METHOD VScroll() CLASS TScrDlg
LOCAL nNewPos

   if ::nVPos >= ::oDlg:oVScroll:nMin   ;
      .and. ::nVPos <= ::oDlg:oVScroll:nMax
      nNewPos := ::oDlg:oVScroll:GetPos()
      SysRefresh()

      ScrollWindow( ::oDlg:hWnd, 0,  ;
         (  ::nVPos-nNewPos )*d_height,    ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nVPos := nNewPos
   endif
RETURN( NIL )

METHOD VScrollThumb(nNewPos) CLASS TScrDlg
   if ::nVPos >= ::oDlg:oVScroll:nMin   ;
      .and. ::nVPos <= ::oDlg:oVScroll:nMax
      ::oDlg:oVScroll:SetPos(nNewPos)
      SysRefresh()
      ScrollWindow( ::oDlg:hWnd, 0,  ;
         (::nVPos - nNewPos )*d_height,    ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nVPos := nNewPos
   endif
RETURN( NIL )

METHOD VScrollTrack(nNewPos) CLASS TScrDlg
   if ::nVPos >= ::oDlg:oVScroll:nMin   ;
      .and. ::nVPos <= ::oDlg:oVScroll:nMax
      ::oDlg:oVScroll:SetPos(nNewPos)
      SysRefresh()
      ScrollWindow( ::oDlg:hWnd, 0,  ;
         (::nVPos - nNewPos )*d_height,    ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nVPos := nNewPos
   endif
RETURN( NIL )

METHOD VScrollPgDown() CLASS TScrDlg
LOCAL nNewPos
   if ::nVPos < ::oDlg:oVScroll:nMax
      nNewPos := ::nVPos + ::oDlg:oVScroll:nPgStep
      nNewPos := iif(nNewPos > ::oDlg:oVScroll:nMax, ::oDlg:oVScroll:nMax, nNewPos)
      SysRefresh()
      ScrollWindow( ::oDlg:hWnd, 0,  ;
         ( ::nVPos - nNewPos )*d_height,    ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nVPos := nNewPos
   endif
RETURN( NIL )

METHOD VScrollPgUp() CLASS TScrDlg
LOCAL nNewPos
   if ::nVPos > ::oDlg:oVScroll:nMin
      nNewPos := ::nVPos - ::oDlg:oVScroll:nPgStep
      nNewPos := iif(nNewPos < ::oDlg:oVScroll:nMin,::oDlg:oVScroll:nMin,nNewPos)
      SysRefresh()
      ScrollWindow( ::oDlg:hWnd, 0,  ;
         ( ::nVPos - nNewPos )*d_height,    ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nVPos := nNewPos
   endif
RETURN( NIL )

//=================================================================
//-* Horizontal Scroll Bar
METHOD HScroll() CLASS TScrDlg
LOCAL nNewPos

   if ::nHPos >= ::oDlg:oHScroll:nMin   ;
      .and. ::nHPos <= ::oDlg:oHScroll:nMax
      nNewPos := ::oDlg:oHScroll:GetPos()
      SysRefresh()
      ScrollWindow( ::oDlg:hWnd,           ;
         (::nHPos - nNewPos )*d_width,0,   ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nHPos := nNewPos
   endif
RETURN( NIL )

METHOD HScrollThumb(nNewPos) CLASS TScrDlg
   if ::nHPos >= ::oDlg:oHScroll:nMin   ;
      .and. ::nHPos <= ::oDlg:oHScroll:nMax
      ::oDlg:oHScroll:SetPos(nNewPos)
      SysRefresh()
      ScrollWindow( ::oDlg:hWnd,           ;
         (::nHPos - nNewPos )*d_width,0,   ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nHPos := nNewPos
   endif
RETURN( NIL )

METHOD HScrollTrack(nNewPos) CLASS TScrDlg
   if ::nHPos >= ::oDlg:oHScroll:nMin   ;
      .and. ::nHPos <= ::oDlg:oHScroll:nMax
      ::oDlg:oHScroll:SetPos(nNewPos)
      SysRefresh()
      ScrollWindow( ::oDlg:hWnd,           ;
         (::nHPos - nNewPos )*d_width,0,   ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nHPos := nNewPos
   endif
RETURN( NIL )

METHOD HScrollPgDown() CLASS TScrDlg

LOCAL nNewPos
   if ::nHPos < ::oDlg:oHScroll:nMax
      nNewPos := ::nHPos + ::oDlg:oHScroll:nPgStep
      nNewPos := iif(nNewPos > ::oDlg:oHScroll:nMax, ::oDlg:oHScroll:nMax, nNewPos)
      SysRefresh()
      ScrollWindow( ::oDlg:hWnd,           ;
         ( ::nHPos - nNewPos )*d_width,0,  ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nHPos := nNewPos
   endif
RETURN( NIL )

METHOD HScrollPgUp() CLASS TScrDlg
LOCAL nNewPos
   if ::nHPos > ::oDlg:oHScroll:nMin
      nNewPos := ::nHPos - ::oDlg:oHScroll:nPgStep
      nNewPos := iif(nNewPos < ::oDlg:oHScroll:nMin,::oDlg:oHScroll:nMin,nNewPos)
      SysRefresh()
      ScrollWindow( ::oDlg:hWnd,           ;
         ( ::nHPos - nNewPos )*d_width,0,  ;
         0 , GetClientRect(::oDlg:hWnd) )
      ::nHPos := nNewPos
   endif
RETURN( NIL )

//=* End of File =================================================

//#include "wndscrol.c"

 


I request our members to test it further, on different Windows OS environments.
I have tested this on Windows XP, Service Pack 2

Regards,

- Ramesh Babu P
Last edited by RAMESHBABU on Thu Dec 01, 2011 2:03 pm, edited 1 time in total.
User avatar
RAMESHBABU
 
Posts: 624
Joined: Fri Oct 21, 2005 5:54 am
Location: Secunderabad (T.S), India

Re: Any guide on creating DPI-aware apps?

Postby RAMESHBABU » Thu Dec 01, 2011 1:59 pm

Hi Members,

It would be nice if the cursor is moved up/down based on pressing TAB or SHIFT+TAB or
ENTER key to go down, accordingly scroll bar automatically moved upwards or downwards
and the current get is visible. :)

I request the members who are all using this Scrollable Dialogue Class to try it.

Regards,

- Ramesh Babu P
User avatar
RAMESHBABU
 
Posts: 624
Joined: Fri Oct 21, 2005 5:54 am
Location: Secunderabad (T.S), India

Re: Any guide on creating DPI-aware apps?

Postby Antonio Linares » Thu Dec 01, 2011 2:04 pm

Ramesh,

Very good! Thanks! :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42085
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Any guide on creating DPI-aware apps?

Postby hua » Fri Dec 02, 2011 2:02 am

Thank you for the prompt reply Antonio. Sorry for the late reply, was dragged to solve something that was deemed higher priority by management.

Ramesh, thank you! :) I'm gonna try your solution now.


RAMESHBABU wrote:It would be nice if the cursor is moved up/down based on pressing TAB or SHIFT+TAB or
ENTER key to go down, accordingly scroll bar automatically moved upwards or downwards
and the current get is visible. :)

I agree with you on this
FWH 11.08/FWH 19.12
BCC5.82/BCC7.3
xHarbour/Harbour
hua
 
Posts: 1072
Joined: Fri Oct 28, 2005 2:27 am

Re: Any guide on creating DPI-aware apps?

Postby hua » Mon Dec 05, 2011 2:50 am

I find the following tutorial has been quite useful:
http://www.rw-designer.com/DPI-aware
FWH 11.08/FWH 19.12
BCC5.82/BCC7.3
xHarbour/Harbour
hua
 
Posts: 1072
Joined: Fri Oct 28, 2005 2:27 am


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 113 guests