FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour Any guide on creating DPI-aware apps?
Posts: 1096
Joined: Fri Oct 28, 2005 02:27 AM

Any guide on creating DPI-aware apps?

Posted: Wed Nov 30, 2011 09: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:


This is what should be seen:


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
Posts: 1096
Joined: Fri Oct 28, 2005 02:27 AM

Re: Any guide on creating DPI-aware apps?

Posted: Wed Nov 30, 2011 09: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
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Re: Any guide on creating DPI-aware apps?

Posted: Wed Nov 30, 2011 02:18 PM

Hua,

Thanks for your feedback! :-)

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Re: Any guide on creating DPI-aware apps?

Posted: Wed Nov 30, 2011 02:30 PM
Hua,

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

I think that in these lines:
Code (fw): Select all Collapse
   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
Posts: 654
Joined: Fri Oct 21, 2005 05:54 AM

Re: Any guide on creating DPI-aware apps?

Posted: 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 (fw): Select all Collapse
#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
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Re: Any guide on creating DPI-aware apps?

Posted: 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
Posts: 654
Joined: Fri Oct 21, 2005 05:54 AM

Re: Any guide on creating DPI-aware apps?

Posted: Thu Dec 01, 2011 01: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.



Code (fw): Select all Collapse
// 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 
      //::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 
    //::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
Posts: 654
Joined: Fri Oct 21, 2005 05:54 AM

Re: Any guide on creating DPI-aware apps?

Posted: Thu Dec 01, 2011 01: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
Posts: 44162
Joined: Thu Oct 06, 2005 05:47 PM

Re: Any guide on creating DPI-aware apps?

Posted: Thu Dec 01, 2011 02:04 PM

Ramesh,

Very good! Thanks! :-)

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 1096
Joined: Fri Oct 28, 2005 02:27 AM

Re: Any guide on creating DPI-aware apps?

Posted: Fri Dec 02, 2011 02: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
Posts: 1096
Joined: Fri Oct 28, 2005 02:27 AM

Re: Any guide on creating DPI-aware apps?

Posted: Mon Dec 05, 2011 02: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

Continue the discussion