Solved

Show/Hide controls in CDialog

Posted on 2007-03-19
12
832 Views
Last Modified: 2013-11-20
I would like to place a button Hide Details on a CDialog derived dialog box which contains several controls. When the user presses the button, some of the controls are hidden and the dialog box is resized correspondingly. Button caption changes to Show Details. When the user presses the button, those hidden controls are shown and dialog box resizes back to original size.
For simplicity, you can assume that controls to hide take the whole line in the dialog so that the dialog is resized only vertically. At the same time, they are not necessarily located at the top or bottom of the dialog.
Please provide detailed code sample for showing/hiding controls and resizing dialog box on a button click event and OnInitDialog().
0
Comment
Question by:polyanovsky
  • 6
  • 6
12 Comments
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 18750707
To show or hide
GetDlgItem(IDC_EDIT1)->ShowWindow(SW_SHOW);  //SW_HIDE

To resize
CRect rc;
GetWindowRect(&rc);
int iWidth = rc.Width();
int iHeight = rc.Height() - 30;  //make it 30 pixels smaller vertically
SetWindowPos(NULL, 0, 0, iWidth, iHeight, SWP_NOMOVE | SWP_NOZORDER);

You can use GetWindowRect and ScreenToClient to find the widht, height and position of any window.
0
 

Author Comment

by:polyanovsky
ID: 18764373
How would I calculate corresponding change in vertical size so that remaining controls are still spaced properly in vertical direction? Replacing 30 pixels in the example above with calculated value is the most difficult part of this question. You may assume that I know the highest top point and the lowest bottom point for controls in the line to hide. Then probably spacing from  controls above and below controls to hide should be taken into account.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 18764542
Say you have the following over three 'lines' in the dialog
A
B
C
and you want to hide line B.
Find the top of line B and the top of line C, the difference is what you need to move line C up and is also the reduction in height of the dialog.

(Trick - there is nothing to stop you having a hidden control of two to help with the sizing/moving. )
0
 

Author Comment

by:polyanovsky
ID: 18766009
(Trick - there is nothing to stop you having a hidden control of two to help with the sizing/moving. )
I did not quite understand what you mean in this remark.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 18766486
A hidden control doesn't need to be moved - that can help when you are moving other controls and then later moving them back to the original location.
0
 

Author Comment

by:polyanovsky
ID: 18771840
Thanks. Actually, I have to move not only line C in the example above but all lines below line B. Is there any way to iterate through all dialog controls? Then I would shift up only controls whose top is below line B bottom.
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 44

Expert Comment

by:AndyAinscow
ID: 18771921
CWnd::GetWindow
use GW_CHILD to get the first then GW_HWNDNEXT inside a loop.  For each window found check if it need to be moved.
0
 

Author Comment

by:polyanovsky
ID: 18772465
Please give me a couple of days to implement this solution (I work on other projects too). If it works as expected I'll accept it.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 18772558
No problems
0
 

Author Comment

by:polyanovsky
ID: 18780541
Hidden controls overlap with shown controls so that when restoring them I have do distinguish between hidden and shown controls to move everything back properly. How could I do that?
0
 
LVL 44

Accepted Solution

by:
AndyAinscow earned 500 total points
ID: 18780606
pWnd->IsWindowVisible();
0
 

Author Comment

by:polyanovsky
ID: 18793065
Here is complete solution for grateful future generations:
MyDlg
A
B
C
D
E
F
G

class CMyDlg: public CDialog
{
.....

private:
      void HideLine(CUIntArray&, int&);
      void ShowLine(CUIntArray&, int);
      void ResizeDialog(int);
      void ShowCtrls(CUIntArray&, int);
      void MoveCtrlsBelow(int, int, int);
      int GetShift(CRect);
      CUIntArray m_arrayCtrlsLineA;
      int m_iShiftLineA;
      int m_iShiftLineF;
      CUIntArray m_arrayCtrlsLineF;
      CRect GetLineRect(CUIntArray&);
      BOOL m_bHide;
}
BOOL CMyDlg::OnInitDialog()
{
      CWfDlg::OnInitDialog();
      .......
      m_arrayCtrlsLineA.Add(IDC_CHECK_LineA);
      m_arrayCtrlsLineA.Add(IDC_STATIC_LineA);
      m_arrayCtrlsLineA.Add(IDC_COMBO_LineA);
      m_arrayCtrlsLineF.Add(IDC_CHECK_LineF);
      m_arrayCtrlsLineF.Add(IDC_STATIC_LineF);
      m_arrayCtrlsLineF.Add(IDC_COMBO_LineF);
      return TRUE;  // return TRUE unless you set the focus to a control
                    // EXCEPTION: OCX Property Pages should return FALSE
}
void CMyDlg::OnButtonShowHideLines()
{
      // TODO: Add your control notification handler code here
      if(m_bHide)
      {
            HideLine(m_arrayCtrlsLineA,m_iShiftLineA);
            HideLine(m_arrayCtrlsLineF,m_iShiftLineF);
            m_bHide=FALSE;
      }
      else
      {
            ShowLine(m_arrayCtrlsLineA,m_iShiftLineA);
            ShowLine(m_arrayCtrlsLineF,m_iShiftLineF);
            m_bHide=TRUE;
      }
}

void CMyDlg::HideLine(CUIntArray& arrayCtrlIDs, int& iShift)
{
            CRect rc=GetLineRect(arrayCtrlIDs);
            iShift=GetShift(rc);
            ShowCtrls(arrayCtrlIDs,SW_HIDE);
            MoveCtrlsBelow(rc.bottom, -iShift, MOVE_VISIBLE|MOVE_HIDDEN);//move all up      
            ResizeDialog(-iShift);
}

void CMyDlg::ShowLine(CUIntArray& arrayCtrlIDs, int iShift)
{
            CRect rc=GetLineRect(arrayCtrlIDs);
            //here is the trik
            MoveCtrlsBelow(rc.top,iShift, MOVE_VISIBLE);//move visible down
            ShowCtrls(arrayCtrlIDs,SW_SHOW);//must be here
            MoveCtrlsBelow(rc.top,iShift, MOVE_HIDDEN);//move hidden down
            ResizeDialog(iShift);
}


CRect CMyDlg::GetLineRect(CUIntArray & arrayCtrlIDs)
{
  CRect rcLine;
  rcLine.top=rcLine.bottom=rcLine.left=rcLine.right=0;
  for(int i=0; i<arrayCtrlIDs.GetSize();++i)
  {
      CWnd* pWnd=GetDlgItem(arrayCtrlIDs.GetAt(i));
      if(!pWnd)
            continue;

      CRect rc;
      pWnd->GetWindowRect(rc);
      if(!rcLine.top||rc.top<rcLine.top)
            rcLine.top=rc.top;
      if(!rcLine.bottom||rc.bottom>rcLine.bottom)
            rcLine.bottom=rc.bottom;
      if(!rcLine.left||rc.left<rcLine.left)
            rcLine.left=rc.left;
      if(!rcLine.right||rc.right>rcLine.right)
            rcLine.right=rc.right;
  }
  return rcLine;
}

int CMyDlg::GetShift(CRect rcLine)
{
      CRect rc;
      GetWindowRect(rc);
      int iMinTop=rc.bottom;//dialog's bottom if there is no controls below
      CWnd* pWnd=GetWindow(GW_CHILD);
      while(pWnd)
      {
            pWnd->GetWindowRect(rc);
            
            if(rc.top>rcLine.bottom&&rc.top<iMinTop)//below the line but higher than other
                  iMinTop=rc.top;
                  
            pWnd=pWnd->GetWindow(GW_HWNDNEXT);  
      }

      return iMinTop-rcLine.top;
}

void CMyDlg::ShowCtrls(CUIntArray & arrayCtrlIDs, int iCmd)
{
      
  for(int i=0; i<arrayCtrlIDs.GetSize();++i)
  {
      CWnd* pWnd=GetDlgItem(arrayCtrlIDs.GetAt(i));
      if(!pWnd)
            continue;

      pWnd->ShowWindow(iCmd);  
  }
}

void CMyDlg::MoveCtrlsBelow(int iY, int iShift, int iType)
{
  //move everything below iY
    CRect rc;
    CWnd* pWnd;
      pWnd=GetWindow(GW_CHILD);
      while(pWnd)
      {
            pWnd->GetWindowRect(rc);
            if(rc.top>=iY&&(
                  ((iType&MOVE_VISIBLE)&&pWnd->IsWindowVisible())||
                  ((iType&MOVE_HIDDEN)&&!pWnd->IsWindowVisible())))
            {
                  ScreenToClient(rc);
                  rc.OffsetRect(0,iShift);
                  pWnd->MoveWindow(rc);
            }

            pWnd=pWnd->GetWindow(GW_HWNDNEXT);  
      }
}

void CMyDlg::ResizeDialog(int iShift)
{
  //resize dlg
      CRect rc;
      GetWindowRect(&rc);
      int iWidth = rc.Width();
      int iHeight = rc.Height() + iShift;  
      SetWindowPos(NULL, 0, 0, iWidth, iHeight, SWP_NOMOVE | SWP_NOZORDER);
      RedrawWindow();
}

0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
configuration management 2 100
repeatEnd java challenge 42 83
Process filename extension 3 156
maven archtype selection in eclipse 1 51
Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now