Change GUI control position with dialog re-size
Change GUI control position with dialog re-size
Introduction
I think many of us had faced an issue that GUI controls were missing actual positions while re-sizing. This could be a serious problem while working with products; which are indented to run on different resolutions. This may happened because of two reasons;
- Re-sizing of the GUI at runtime
- Accidental modifications to the resource file.
We can solve this issue by using relative positions for controls. So normally the next question should be How to implement? I think many of the programmers have their on way to solve this issue. Here I am trying to present my idea. I do not argue that this is the only method, your suggestions are always welcome.
Using the Code
Below is the figure of my dialog, first image is from resource editor and second one is the expected GUI.
For implementing this first of all you need to have a detail specification about your GUI; like its initial position, controls initial and relative position. I implemented the below logic according to my requirement; you can apply your own logic.
// Main Window Initial X and Y Positions
const int MAIN_WINDOW_START_X = 100;
const int MAIN_WINDOW_START_Y = 100;
// Main Window Initial Width and Height
const int MAIN_WINDOW_WIDTH = 800;
const int MAIN_WINDOW_HEIGHT = 800;
// Edit control Initial X and Y Positions relative to Main window
const int EDIT_START_X = 20;
const int EDIT_START_Y = 30;
// Edit control width and height factor relative to Main window
const float EDIT_WIDTH_F = 0.7;
const float EDIT_HEIGHT_F = 0.8;
// All other controls X Position = middle position between Edit control and window end
// All other controls Y Position = Spacd in 50 unit intervels fromEdit control bottom
// All other controls Width and Height factor relative to distance between Main window and edi// t control.
const float CONTROL_WIDTH_F = 0.3;
const float CONTROL_HEIGHT_F = 0.5;
const int CONTROL_INTER = 50;
Next I am going to add a function to resize my controls according to my specifications
void CPositionsDlg::ArrangeControls( int cX, int cY )
{
// Calculating Edit control width and height
int nEditBoxW = EDIT_WIDTH_F * cX;
int nEditBoxH = EDIT_HEIGHT_F * cY;
// Setting Edit Control Positions
::SetWindowPos( GetDlgItem( IDC_EDIT1 )->m_hWnd, HWND_TOP ,
EDIT_START_X , EDIT_START_Y, nEditBoxW, nEditBoxH, NULL );
// Distance between Edit control and Window right
int nDist = ( cX - nEditBoxW );
int nMiddle = nEditBoxW + nDist / 2;
int nControlWidth = nDist * CONTROL_WIDTH_F;
int nControlHeight = nControlWidth * CONTROL_HEIGHT_F;
int nControlXpos =nMiddle - ( nControlWidth / 2 );
int nControlYpos =nEditBoxH - ( nControlHeight / 2 );
// Cancel button
::SetWindowPos( GetDlgItem( IDCANCEL )->m_hWnd, HWND_TOP ,
nControlXpos , nControlYpos, nControlWidth,
nControlHeight, NULL );
// Ok button
nControlYpos -= CONTROL_INTER;
::SetWindowPos( GetDlgItem( IDOK )->m_hWnd, HWND_TOP ,
nControlXpos , nControlYpos, nControlWidth,
nControlHeight, NULL );
// Radio button
nControlYpos -= CONTROL_INTER;
::SetWindowPos( GetDlgItem( IDC_RADIO1 )->m_hWnd, HWND_TOP ,
nControlXpos , nControlYpos, nControlWidth,
nControlHeight, NULL );
// Combo Box
nControlYpos -= CONTROL_INTER;
::SetWindowPos( GetDlgItem( IDC_COMBO1 )->m_hWnd, HWND_TOP ,
nControlXpos , nControlYpos, nControlWidth,
nControlHeight, NULL );
}
The above function and its calculations may be different with different requirements, I have just shown one sample.
The next thing is to set the main window position, the best place for this operations is OnInitDialog()
method.
BOOL CPositionsDlg::OnInitDialog()
{
.......................
// TODO: Add extra initialization here
SetWindowPos( NULL, 100, 100, 800, 800, NULL );
return TRUE; // return TRUE unless you set the focus to a control
}
Now we have our control position calculation code and Main window, next we need to place our ArrangeControls()
method. The best
place is ON_WM_SIZE message handler, you need to do a little bit more to implement this. Because this function should be called during main window creation and our controls
were not created at that time. This may cause crash in our application. So we include one checking, IsWindowVisible()
to verify if our main window exists or not.
void CPositionsDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
if( ::IsWindowVisible( this->m_hWnd ))
{
ArrangeControls( cx, cy);
}
}
Now it is almost ok but there exists one more issue, i.e our ArrangeControls()
is never been called because of the IsWindowVisible()
checking. If we try to re-size the GUI, the ArrangeControls()
method handle the re-sizing. So for setting controls on proper positions during
initialization we need to call ArrangeControls()
from ON_WM_SHOWWINDOW
message handler.
void CPositionsDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialogEx::OnShowWindow(bShow, nStatus);
ArrangeControls( MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT );
}
Now everything is ready for our purpose; you can enjoy freedom of resizing.
History
Version 2
- June-02-2012: Updated the entire document for including more detail.