/*
   --------------------------------------------------------
   Filename.....: winposition.cc
   ClassName....: winPosition
   Programmer...: Rick Miller
   Date.........: February 06, 2001
   Purpose......: non-GUI Object to hold the windows desktop
                  position for a GUI object, GUI client area,
                  or the Window's working desktop area.
   Notes........: Property values are in Pixels.
   Written for..: dB2K 01 and newer.
   Rev. History.: See Revisions below.
   Dependencies.: None.
   Calls........: see x_InitializeExterns method for API calls.
   Called by....: Any.
   Usage........: set procedure to winposition.cc additive
   Example......: See below.
   ----------------------------------------------------------------
   Example:
   ----------------------------------------------------------------
      oRef  =  new winPosition()
      oRef.get(int(GUIobject.hWnd))
      oRef.inspect()
   ----------------------------------------------------------------
   Properties:
   ----------------------------------------------------------------
      bottom      <int>    desktop bottom position.
      height      <int>    object height.
      left        <int>    desktop left position.
      right       <int>    desktop right position.
      top         <int>    desktop top position.
      width       <int>    object width.
   ----------------------------------------------------------------
   Methods:
   ----------------------------------------------------------------
      get([<int or oRef> hWnd or GUI object])
         assign properties based upon a GUI object position.
         return true/false (success/fail).
      getClient([<int or oRef> hWnd or GUI object])
         assign properties based upon a GUI object client area.
         return true/false (success/fail).
      getDesktop()
         assign properties based upon the Desktop working area.
         return true/false (success/fail).
      inspect()   display object in the inspector.
      release()   destroy object.
   ----------------------------------------------------------------
   Revisions:
   ----------------------------------------------------------------
      September 14, 2006
      -------------------------------------------------------------
         1) reduced code size by adding the common method
            x_AssignProps for the get(??) methods.
         2) change the external function name, for an API call,
            added on September 05, 2006.
      -------------------------------------------------------------
      September 05, 2006
      -------------------------------------------------------------
         1) added getClient method.
         2) added getDesktop method.
      -------------------------------------------------------------
      August 09, 2005
      -------------------------------------------------------------
         1) updated for dUFLP.
      -------------------------------------------------------------
      February 10, 2005
      -------------------------------------------------------------
         1) renamed all external functions.
      -------------------------------------------------------------
      January 01, 2005
      -------------------------------------------------------------
         1) verified external functions.
   ----------------------------------------------------------------
   */
#define  WINPOSITION_CLASSNAME      "winPosition"
#define  WINPOSITION_PUBLISHINFO    "Rick Miller"
#define  WINPOSITION_VERSIONINFO    "6.0914"
#define  SPI_GETWORKAREA            (48)  // Desktop Client Area.
#define  ZEROS(n)                   replicate(chr(0), n)
//---------------------------------------------------------------//
//          constructor.
//---------------------------------------------------------------//
class winPosition
   this.className    =  WINPOSITION_CLASSNAME

   this.top    =  0
   this.left   =  0
   this.right  =  0
   this.bottom =  0
   this.height =  0
   this.width  =  0

   this.versioninfo  =  WINPOSITION_VERSIONINFO
   this.publishinfo  =  WINPOSITION_PUBLISHINFO

   // protected methods.
   protect  x_AssignProps, x_GetHwnd, x_GetRectValue,;
            x_InitializeExterns
   class::x_InitializeExterns()

   //------------------------------------------------------------//
   //       end of constructor   -  methods below.
   //------------------------------------------------------------//
   // get and store the window's position and size
   //    of the passed object, object.hWnd, parent.hWnd,
   //    _app.framewin.hWnd, or returns false.
   // NOTE: position and size values are in Pixels.
   function get(p1)
      Local bRet, nHwnd
      bRet  =  false
      nHwnd =  this.x_GetHwnd(p1)
      if not nHwnd == 0
         Local sRect
         sRect =  ZEROS(8)
         if RMM_GetWindowRect(nHwnd, sRect)
            this.x_AssignProps(sRect)
            bRet  := true
         endif
      endif
   return   iif(bRet, true, false)
   // return true/false (success/fail)

   //------------------------------------------------------------//
   // get and store the client area size
   //    of the passed object, object.hWnd,
   //    parent.hWnd, _app.framewin.hWnd, or returns false.
   // NOTE: client area size values are in Pixels.
   function getClient(p1)
      Local bRet, nHwnd
      bRet  =  false
      nHwnd =  this.x_GetHwnd(p1)
      if not nHwnd == 0
         Local sRect
         sRect =  ZEROS(8)
         if RMM_GetClientRect(nHwnd, sRect)
            this.x_AssignProps(sRect)
            bRet  := true
         endif
      endif
   return   iif(bRet, true, false)
   // return true/false (success/fail)

   //------------------------------------------------------------//
   // get and store the desktop working area position and size.
   // the working area is the portion of the screen not obscured
   //    by the system tray.
   // NOTE: position and size values are in Pixels.
   function getDesktop
      Local bRet, sRect
      bRet  =  false
      sRect =  ZEROS(8)
      if RMM_GetDesktopClientRect(SPI_GETWORKAREA, 0, sRect, 0)
         this.x_AssignProps(sRect)
         bRet  := true
      endif
   return   iif(bRet, true, false)
   // return true/false (success/fail)

   //------------------------------------------------------------//
   // display this in the inspector.
   function inspect
      inspect(this)
   return

   //------------------------------------------------------------//
   // release object from memory.
   function release
      try
         release object this
      catch(exception e)
      endtry
   return

   //------------------------------------------------------------//
   // sRect =  a rect string.
   // assign property values from the passed in sRect.
   function x_AssignProps(sRect)
      this.left   := int(class::x_GetRectValue(sRect, 0))
      this.top    := int(class::x_GetRectValue(sRect, 4))
      this.right  := int(class::x_GetRectValue(sRect, 8))
      this.bottom := int(class::x_GetRectValue(sRect, 12))
      this.width  := int(this.right - this.left)
      this.height := int(this.bottom - this.top)
   return

   //------------------------------------------------------------//
   function x_GetHwnd
      parameters pIn
      if type("pIn") == "N"
         nRet  =  int(pIn)
      elseif type("pIn.hWnd") == "N"
         nRet  =  int(pIn.hWnd)
      elseif type("this.parent.hWnd") == "N"
         nRet  =  int(this.parent.hWnd)
      elseif type("_app.framewin.hWnd") == "N"
         nRet  =  int(_app.framewin.hWnd)
      else
         nRet  =  0
      endif
   return   nRet

   //------------------------------------------------------------//
   function x_GetRectValue(sRect, nPos)
      Local nRet
      nRet  =  sRect.getByte(nPos) +;
         bitLshift(sRect.getByte(nPos + 1), 8) +;
         bitLshift(sRect.getByte(nPos + 2), 16) +;
         bitLshift(sRect.getByte(nPos + 3), 24)
      if bitSet(nRet, 31)
         nRet  := - bitNot(nRet)
      endif
   return   nRet

   //------------------------------------------------------------//
   // declare functions external to dBASE.
   function x_InitializeExterns
      if not type("RMM_GetClientRect") == "FP"
         extern CLOGICAL RMM_GetClientRect(CHANDLE, CPTR) ;
            user32 from "GetClientRect"
      endif
      if not type("RMM_GetDesktopClientRect") == "FP"
         extern CLOGICAL RMM_GetDesktopClientRect( ;
            CUINT, CUINT, CPTR, CUINT) ;
            user32 from "SystemParametersInfoA"
      endif
      if not type("RMM_GetWindowRect") == "FP"
         extern CLOGICAL RMM_GetWindowRect(CHANDLE, CPTR) ;
            user32 from "GetWindowRect"
      endif
   return true

endclass
//---------------------------------------------------------------//
//          end of winPosition.
//---------------------------------------------------------------//