How to SetWindowPos correctly? Actually confused with GetClientRect,GetWindowRect,ScreenToClient and ClientToScreen etc.
-
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.
-
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.
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:
-
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:
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
-
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
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
-
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
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:
-
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
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 coordinatem_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
-