Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. How to SetWindowPos correctly? Actually confused with GetClientRect,GetWindowRect,ScreenToClient and ClientToScreen etc.

How to SetWindowPos correctly? Actually confused with GetClientRect,GetWindowRect,ScreenToClient and ClientToScreen etc.

Scheduled Pinned Locked Moved C / C++ / MFC
c++tutorialquestion
6 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    fantasy1215
    wrote on last edited by
    #1

    when create a dialog based MFC project defaultly, we have the OK, cancel buttons in the topright corner, I want to create a CListBox dynamicly and place it in the position relative to the IDOK button( the top cordination of CListBox is the same as IDOK), so I write my code like below: first, construct a CListBox in the .h file CListBox m_ctlBox; then, within the OnInitDialog

    BOOL CMyDialog::OnInitDialog()
    {
    CDialog::OnInitDialog();
    m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0), rightcode);
    m_ctlBox.ShowWindow(SW_HIDE);

    //below code to set the position for the CListBox
    CRect rcOK;
    GetDlgItem(IDOK)->GetWindowRect(&rcOK);
    int nBoxWidth = 30;
    int nBoxHeight = 40;
    int nxMargin = 10;
    int nBoxTop = rcOK.top;
    int nBoxLeft = rcOK.left - nxMargin - nBoxWidth;
    m_ctlBox.SetWindowPos(&CWnd::wndTop, nBoxLeft, nBoxTop, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
    m_ctlBox.ShowWindow(SW_SHOW);
    return TRUE;
    }

    but the m_ctlBox's top is not as IDOK's. Really confused with how to use GetClientRect 、GetWindowRect、ScreenToClient and ClientToScreen correctly to set window position correctly. So I can't write my code to deal with WM_SIZE correctly.

    M 1 Reply Last reply
    0
    • F fantasy1215

      when create a dialog based MFC project defaultly, we have the OK, cancel buttons in the topright corner, I want to create a CListBox dynamicly and place it in the position relative to the IDOK button( the top cordination of CListBox is the same as IDOK), so I write my code like below: first, construct a CListBox in the .h file CListBox m_ctlBox; then, within the OnInitDialog

      BOOL CMyDialog::OnInitDialog()
      {
      CDialog::OnInitDialog();
      m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0), rightcode);
      m_ctlBox.ShowWindow(SW_HIDE);

      //below code to set the position for the CListBox
      CRect rcOK;
      GetDlgItem(IDOK)->GetWindowRect(&rcOK);
      int nBoxWidth = 30;
      int nBoxHeight = 40;
      int nxMargin = 10;
      int nBoxTop = rcOK.top;
      int nBoxLeft = rcOK.left - nxMargin - nBoxWidth;
      m_ctlBox.SetWindowPos(&CWnd::wndTop, nBoxLeft, nBoxTop, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
      m_ctlBox.ShowWindow(SW_SHOW);
      return TRUE;
      }

      but the m_ctlBox's top is not as IDOK's. Really confused with how to use GetClientRect 、GetWindowRect、ScreenToClient and ClientToScreen correctly to set window position correctly. So I can't write my code to deal with WM_SIZE correctly.

      M Offline
      M Offline
      Mark Salsbery
      wrote on last edited by
      #2

      GetWindowRect()  gets coords relative to the screen. SetWindowPos() is expecting coords relative to the parents client area.

      BOOL CMyDialog::OnInitDialog()
      {
      CDialog::OnInitDialog();
      m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0), this);
      m_ctlBox.ShowWindow(SW_HIDE); //<-- you could create the window without the WS_VISIBLE style to avoid potential flash doing this

      //below code to set the position for the CListBox
      CRect rcOK;
      GetDlgItem(IDOK)->GetWindowRect(&rcOK);
      int nBoxWidth = 30;
      int nBoxHeight = 40;
      int nxMargin = 10;
      CPoint BoxUpperLeft;
      BoxUpperLeft.y = rcOK.top;
      BoxUpperLeft.x = rcOK.left - nxMargin - nBoxWidth;
      ScreenToClient(&BoxUpperLeft); //<-- converts screen coords to coords relative to this window m_ctlBox.SetWindowPos(&CWnd::wndTop, BoxUpperLeft.x, BoxUpperLeft.y, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
      m_ctlBox.ShowWindow(SW_SHOW);
      return TRUE;
      }

      Mark

      Mark Salsbery Microsoft MVP - Visual C++ :java:

      F 1 Reply Last reply
      0
      • M Mark Salsbery

        GetWindowRect()  gets coords relative to the screen. SetWindowPos() is expecting coords relative to the parents client area.

        BOOL CMyDialog::OnInitDialog()
        {
        CDialog::OnInitDialog();
        m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0), this);
        m_ctlBox.ShowWindow(SW_HIDE); //<-- you could create the window without the WS_VISIBLE style to avoid potential flash doing this

        //below code to set the position for the CListBox
        CRect rcOK;
        GetDlgItem(IDOK)->GetWindowRect(&rcOK);
        int nBoxWidth = 30;
        int nBoxHeight = 40;
        int nxMargin = 10;
        CPoint BoxUpperLeft;
        BoxUpperLeft.y = rcOK.top;
        BoxUpperLeft.x = rcOK.left - nxMargin - nBoxWidth;
        ScreenToClient(&BoxUpperLeft); //<-- converts screen coords to coords relative to this window m_ctlBox.SetWindowPos(&CWnd::wndTop, BoxUpperLeft.x, BoxUpperLeft.y, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
        m_ctlBox.ShowWindow(SW_SHOW);
        return TRUE;
        }

        Mark

        Mark Salsbery Microsoft MVP - Visual C++ :java:

        F Offline
        F Offline
        fantasy1215
        wrote on last edited by
        #3

        Question NO.1

        BOOL CMyDialog::OnInitDialog()
        {
        CDialog::OnInitDialog();
        m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0),this);
        m_ctlBox.ShowWindow(SW_HIDE); //<-- you could create the window without the WS_VISIBLE style to avoid potential flash doing this
        //below code to set the position for the CListBox
        CRect rcOK;
        GetDlgItem(IDOK)->GetWindowRect(&rcOK);
        int nBoxWidth = 30;
        int nBoxHeight = 40;
        int nxMargin = 10;
        CPoint BoxUpperLeft;
        BoxUpperLeft.y = rcOK.top;
        BoxUpperLeft.x = rcOK.left - nxMargin - nBoxWidth;

        //you use
        this->ScreenToClient(&BoxUpperLeft)
        //why not m_ctlBox.ScreenToClient(&BoxUpperLeft); ?

        m_ctlBox.SetWindowPos(&CWnd::wndTop, BoxUpperLeft.x, BoxUpperLeft.y, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
        m_ctlBox.ShowWindow(SW_SHOW);
        return TRUE;
        }

        Question NO.2 and how to do it with GetClientRect()?

        BOOL CMyDialog::OnInitDialog()
        {
        CDialog::OnInitDialog();
        m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0),this);
        m_ctlBox.ShowWindow(SW_HIDE); //<-- you could create the window without the WS_VISIBLE style to avoid potential flash doing this
        //below code to set the position for the CListBox
        CRect rcOK;
        GetDlgItem(IDOK)->GetClientRect(&rcOK);
        int nBoxWidth = 30;
        int nBoxHeight = 40;
        int nxMargin = 10;
        CPoint BoxUpperLeft;
        BoxUpperLeft.y = rcOK.top;
        BoxUpperLeft.x = rcOK.left - nxMargin - nBoxWidth;

        m_ctlBox.SetWindowPos(&CWnd::wndTop, BoxUpperLeft.x, BoxUpperLeft.y, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
        m_ctlBox.ShowWindow(SW_SHOW);
        return TRUE;
        }

        -- modified at 2:40 Wednesday 21st November, 2007

        P M 2 Replies Last reply
        0
        • F fantasy1215

          Question NO.1

          BOOL CMyDialog::OnInitDialog()
          {
          CDialog::OnInitDialog();
          m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0),this);
          m_ctlBox.ShowWindow(SW_HIDE); //<-- you could create the window without the WS_VISIBLE style to avoid potential flash doing this
          //below code to set the position for the CListBox
          CRect rcOK;
          GetDlgItem(IDOK)->GetWindowRect(&rcOK);
          int nBoxWidth = 30;
          int nBoxHeight = 40;
          int nxMargin = 10;
          CPoint BoxUpperLeft;
          BoxUpperLeft.y = rcOK.top;
          BoxUpperLeft.x = rcOK.left - nxMargin - nBoxWidth;

          //you use
          this->ScreenToClient(&BoxUpperLeft)
          //why not m_ctlBox.ScreenToClient(&BoxUpperLeft); ?

          m_ctlBox.SetWindowPos(&CWnd::wndTop, BoxUpperLeft.x, BoxUpperLeft.y, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
          m_ctlBox.ShowWindow(SW_SHOW);
          return TRUE;
          }

          Question NO.2 and how to do it with GetClientRect()?

          BOOL CMyDialog::OnInitDialog()
          {
          CDialog::OnInitDialog();
          m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0),this);
          m_ctlBox.ShowWindow(SW_HIDE); //<-- you could create the window without the WS_VISIBLE style to avoid potential flash doing this
          //below code to set the position for the CListBox
          CRect rcOK;
          GetDlgItem(IDOK)->GetClientRect(&rcOK);
          int nBoxWidth = 30;
          int nBoxHeight = 40;
          int nxMargin = 10;
          CPoint BoxUpperLeft;
          BoxUpperLeft.y = rcOK.top;
          BoxUpperLeft.x = rcOK.left - nxMargin - nBoxWidth;

          m_ctlBox.SetWindowPos(&CWnd::wndTop, BoxUpperLeft.x, BoxUpperLeft.y, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
          m_ctlBox.ShowWindow(SW_SHOW);
          return TRUE;
          }

          -- modified at 2:40 Wednesday 21st November, 2007

          P Offline
          P Offline
          Parthi_Appu
          wrote on last edited by
          #4

          Before going into your question, GetWindowRect(..) will return the window rect with respect to screen cooridates. GetClientRect(..) will return the client area of the window, that is regardless of its position the top left point is 0, 0 and right, bottom point is its width and height respectivly Now for Question 1: You got the screen coordinate of OK button, now you have to find its coordinate with respect to the dialog and not with the listbox. For Question 2: As i said earlier, if you use GetClientRect(..), simply it will return width and height. By knowing only the width and height you can't find its starting (top,left) coordinate.


          Do your Duty and Don't expect the Result

          F 1 Reply Last reply
          0
          • F fantasy1215

            Question NO.1

            BOOL CMyDialog::OnInitDialog()
            {
            CDialog::OnInitDialog();
            m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0),this);
            m_ctlBox.ShowWindow(SW_HIDE); //<-- you could create the window without the WS_VISIBLE style to avoid potential flash doing this
            //below code to set the position for the CListBox
            CRect rcOK;
            GetDlgItem(IDOK)->GetWindowRect(&rcOK);
            int nBoxWidth = 30;
            int nBoxHeight = 40;
            int nxMargin = 10;
            CPoint BoxUpperLeft;
            BoxUpperLeft.y = rcOK.top;
            BoxUpperLeft.x = rcOK.left - nxMargin - nBoxWidth;

            //you use
            this->ScreenToClient(&BoxUpperLeft)
            //why not m_ctlBox.ScreenToClient(&BoxUpperLeft); ?

            m_ctlBox.SetWindowPos(&CWnd::wndTop, BoxUpperLeft.x, BoxUpperLeft.y, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
            m_ctlBox.ShowWindow(SW_SHOW);
            return TRUE;
            }

            Question NO.2 and how to do it with GetClientRect()?

            BOOL CMyDialog::OnInitDialog()
            {
            CDialog::OnInitDialog();
            m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0),this);
            m_ctlBox.ShowWindow(SW_HIDE); //<-- you could create the window without the WS_VISIBLE style to avoid potential flash doing this
            //below code to set the position for the CListBox
            CRect rcOK;
            GetDlgItem(IDOK)->GetClientRect(&rcOK);
            int nBoxWidth = 30;
            int nBoxHeight = 40;
            int nxMargin = 10;
            CPoint BoxUpperLeft;
            BoxUpperLeft.y = rcOK.top;
            BoxUpperLeft.x = rcOK.left - nxMargin - nBoxWidth;

            m_ctlBox.SetWindowPos(&CWnd::wndTop, BoxUpperLeft.x, BoxUpperLeft.y, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
            m_ctlBox.ShowWindow(SW_SHOW);
            return TRUE;
            }

            -- modified at 2:40 Wednesday 21st November, 2007

            M Offline
            M Offline
            Mark Salsbery
            wrote on last edited by
            #5

            There's not an API (or CWnd method) I know of to get the rect of a window relative to its parent, so your GetClientRect() method isn't going to give you the info you need. Remember, the window rect is the outer bounding rect of the window.  The client rect is the interior of the window, excluding borders, title bar, menu, and other "decorations". As Parthi mentioned, the client rect's upper left coord is always 0,0. Controls are windows, so the same rules apply. About Windows[^] MapWindowPoints()[^] Mark

            Mark Salsbery Microsoft MVP - Visual C++ :java:

            1 Reply Last reply
            0
            • P Parthi_Appu

              Before going into your question, GetWindowRect(..) will return the window rect with respect to screen cooridates. GetClientRect(..) will return the client area of the window, that is regardless of its position the top left point is 0, 0 and right, bottom point is its width and height respectivly Now for Question 1: You got the screen coordinate of OK button, now you have to find its coordinate with respect to the dialog and not with the listbox. For Question 2: As i said earlier, if you use GetClientRect(..), simply it will return width and height. By knowing only the width and height you can't find its starting (top,left) coordinate.


              Do your Duty and Don't expect the Result

              F Offline
              F Offline
              fantasy1215
              wrote on last edited by
              #6

              When I see the explaination of the API ::ScreenToClient(), I understand clearly. GetDlgItem(IDOK)->GetWindowRect(&rcOK);* First, rcOK's coordinates are relative to the upper left of the display screen.

              • Then compulate the position of the CListBox to the coordinates relative to display screen.

              • Next we need convert the screen coordinates of the CListBox to the coordinates in the main Dialog's client coordinates. BOOL ScreenToClient( HWND hWnd, // handle to window LPPOINT lpPoint // screen coordinates ); hWnd [in] Handle to the window whose client area will be used for the conversion. so we should pass the dialog's hWnd.

                BOOL CMyDialog::OnInitDialog()
                {
                CDialog::OnInitDialog();
                m_ctlBox.Create(STYLE, CRect(0, 0, 0, 0),this);
                m_ctlBox.ShowWindow(SW_HIDE); //<-- you could create the window without the WS_VISIBLE style to avoid potential flash doing this
                //below code to set the position for the CListBox
                CRect rcOK;
                GetDlgItem(IDOK)->GetWindowRect(&rcOK);
                int nBoxWidth = 30;
                int nBoxHeight = 40;
                int nxMargin = 10;
                CPoint BoxUpperLeft;
                BoxUpperLeft.y = rcOK.top;
                BoxUpperLeft.x = rcOK.left - nxMargin - nBoxWidth;

                ::ScreenToClient(this->m_hWnd, &BoxUpperLeft);
                //This code first compulate the CListBox screen coordinate then convert to the Dialog client coordinate

                m_ctlBox.SetWindowPos(&CWnd::wndTop, BoxUpperLeft.x, BoxUpperLeft.y, nBoxWidth, nBoxHeight, SWP_SHOWWINDOW);
                m_ctlBox.ShowWindow(SW_SHOW);
                return TRUE;
                }

                If somewhere is wrong, please correct me! thx. -- modified at 0:17 Thursday 22nd November, 2007

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups