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.
Fig 1: From Resource Editor
Fig 2: 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.
const int MAIN_WINDOW_START_X = 100;
const int MAIN_WINDOW_START_Y = 100;
const int MAIN_WINDOW_WIDTH = 800;
const int MAIN_WINDOW_HEIGHT = 800;
const int EDIT_START_X = 20;
const int EDIT_START_Y = 30;
const float EDIT_WIDTH_F = 0.7;
const float EDIT_HEIGHT_F = 0.8;
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 )
{
int nEditBoxW = EDIT_WIDTH_F * cX;
int nEditBoxH = EDIT_HEIGHT_F * cY;
::SetWindowPos( GetDlgItem( IDC_EDIT1 )->m_hWnd, HWND_TOP ,
EDIT_START_X , EDIT_START_Y, nEditBoxW, nEditBoxH, NULL );
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 );
::SetWindowPos( GetDlgItem( IDCANCEL )->m_hWnd, HWND_TOP ,
nControlXpos , nControlYpos, nControlWidth,
nControlHeight, NULL );
nControlYpos -= CONTROL_INTER;
::SetWindowPos( GetDlgItem( IDOK )->m_hWnd, HWND_TOP ,
nControlXpos , nControlYpos, nControlWidth,
nControlHeight, NULL );
nControlYpos -= CONTROL_INTER;
::SetWindowPos( GetDlgItem( IDC_RADIO1 )->m_hWnd, HWND_TOP ,
nControlXpos , nControlYpos, nControlWidth,
nControlHeight, NULL );
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()
{
.......................
SetWindowPos( NULL, 100, 100, 800, 800, NULL );
return TRUE; }
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.