如何使控件随对话框大小变化而调整大小和位置?

时间:2022-01-03 10:21:32
用MFC写了一个简单的界面,其中有一个Tab控件和一个静态文本控件、两个按钮,Tab控件分有三个Page,引入三个模式对话框,每一个对话框也有不同的控件,目前Tab控件、静态文本及两个按钮可以随对话框窗体大小变化而调整,但对于三个Page中的模式对话框中的子控件,则调整不了,请问各位大侠,应该如何控制?

18 个解决方案

#1


响应WM_SIZE,调用MoveWindow调整控件位置和大小

#2


void CXTest2Dlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
//将窗口移动到合适位置和大小
CRect rc,rc0,rc1;
GetClientRect(&rc0);//先取得整个对话框的大小及位置
//设置Tab控件位置
rc1.top=rc0.top;
rc1.left=rc0.left+1;
rc1.bottom=rc0.bottom-30;
rc1.right=rc0.right-1;
if(GetDlgItem(IDC_TAB1)!=NULL)
{
GetDlgItem(IDC_TAB1)->MoveWindow(&rc1);
}

//设置时钟位置
rc1.top=rc0.bottom-20;
rc1.left=rc0.left+5;
rc1.bottom=rc0.bottom;
rc1.right=rc0.left+160;
if(GetDlgItem(IDC_CLOCKTEST)!=NULL)
{
GetDlgItem(IDC_CLOCKTEST)->MoveWindow(&rc1);
}
//设置关闭按钮位置
rc1.top=rc1.top-5;
rc1.left=rc0.right-200;
rc1.bottom=rc1.bottom;
rc1.right=rc0.right-120;
if(GetDlgItem(IDOK)!=NULL)
{
GetDlgItem(IDOK)->MoveWindow(&rc1);
}
//设置取消按钮位置
rc1.left=rc0.right-100;
rc1.right=rc0.right-20;
if(GetDlgItem(IDCANCEL)!=NULL)
{
GetDlgItem(IDCANCEL)->MoveWindow(&rc1);
}

//将三个对话框资源定位到Tab控件中
if(GetDlgItem(IDC_TAB1)!=NULL)
{
GetDlgItem(IDC_TAB1)->GetClientRect(&rc);
rc1.top=rc.top+20;
rc1.left=rc.left+1;
rc1.bottom=rc.bottom-10;
rc1.right=rc.right-1;
tab1.MoveWindow(&rc1);
tab2.MoveWindow(&rc1);
tab3.MoveWindow(&rc1);
//将三个对话框资源中的控件随对话框大小变化
GetDlgItem(IDC_MSGINFO)->MoveWindow(&rc1);//移动第一个
rc1.bottom=rc.bottom-35;//第二个及第三个底部留出按钮位置
GetDlgItem(IDC_BNSLIST)->MoveWindow(&rc1);
GetDlgItem(IDC_MSGERRINFO)->MoveWindow(&rc1);

}
}
红色部分的代码出错

#3


基本的做法就是响应 wm_size消息,按照窗口大小比例调整控件的位置和大小

#4


以上三楼 正是偶想说的 
^_^
每次OnSize 获得一个CRect 
根据这个CRect 来确定 那些控件的位置 MoveWindow 或者 SetWindowpos

#5


google seach 

CResizeDialog

good luck

#6


tab1.GetClientRect(&rc1);
tab1.GetDlgItem(IDC_MSGINFO)->MoveWindow(&rc1);//移动第一个 
rc1.bottom=rc.bottom-35;//第二个及第三个底部留出按钮位置 
tab2.GetDlgItem(IDC_BNSLIST)->MoveWindow(&rc1); 
tab3.GetDlgItem(IDC_MSGERRINFO)->MoveWindow(&rc1); 

#7


控件的大小最好设置成窗口的 百分之几 这样的话 就可以根据窗口的大小随时调整了

#8


这个就得自己写了,对控件MoveWindow、SetWindowpos。

#9


是否可以响应WM_WINDOWPOSCHANGED消息?对话框的大小位置改变后再据此来调整控件?

#10


http://www.joyvc.cn/GuiAndWindows/GuiAndWindows00040.html

一、简单对话框全屏显示方法
        在OnInitDialog()中任意加入:
        1、ModifyStyle(WS_CAPTION,0,0);   //如果不想去掉标题栏,去掉该句。
                SendMessage(WM_SYSCOMMAND,SC_MAXIMIZE,0); 
        2、ShowWindow(SW_SHOWMAXIMIZED);   
        二、复杂一点的对话框全屏显示方法,随屏幕的分辩率而调节
        void CMainFrame::OnFullScreen()     
        {
                GetWindowPlacement(&m_OldWndPlacement);     
                CRect WindowRect;     
                GetWindowRect(&WindowRect);     
                CRect ClientRect;     
                RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &ClientRect);     
                ClientToScreen(&ClientRect); 
    
                //获取屏幕的分辨率     
                int nFullWidth=GetSystemMetrics(SM_CXSCREEN);     
                int nFullHeight=GetSystemMetrics(SM_CYSCREEN);
     
                //将除控制条外的客户区全屏显示到从(0,0)到(nFullWidth, nFullHeight)区域, 
                //将(0,0)和(nFullWidth, nFullHeight)两个点外扩充原窗口和除控制条之外的
                //客户区位置间的差值, 就得到全屏显示的窗口位置     
                m_FullScreenRect.left=WindowRect.left-ClientRect.left;     
                m_FullScreenRect.top=WindowRect.top-ClientRect.top;     
                m_FullScreenRect.right=WindowRect.right-ClientRect.right+nFullWidth;     
                m_FullScreenRect.bottom=WindowRect.bottom-ClientRect.bottom+nFullHeight;     
                m_bFullScreen=TRUE;   //设置全屏显示标志为TRUE
     
                //进入全屏显示状态     
                WINDOWPLACEMENT wndpl;     
                wndpl.length=sizeof(WINDOWPLACEMENT);     
                wndpl.flags=0;     
                wndpl.showCmd=SW_SHOWNORMAL;     
                wndpl.rcNormalPosition=m_FullScreenRect;     
                SetWindowPlacement(&wndpl);
        } 

        三、对话框全屏及按钮控件移到相应位置
        void CXXXDlg::OnLButtonDown(UINT nFlags, CPoint point)     
        {                     
                int cx=::GetSystemMetrics(SM_CXSCREEN);   
                int cy=::GetSystemMetrics(SM_CYSCREEN);   
    
                CRect rtClient,rtBtn;   
                CWnd  *pWnd=GetDlgItem(IDC_BUTTON);   
    
                GetClientRect(&rtClient);             //获得对话框客户区屏幕坐标   
                ClientToScreen(&rtClient);            //映射为屏幕坐标   
                pWnd->GetWindowRect(&rtBtn);          //获得button屏幕坐标   
   
                int lx=rtBtn.Width();                 //button长度   
                int ly=rtBtn.Height();                //button高度   
                int dx=rtClient.right-rtBtn.right;    //离右边框的距离   
                int dy=rtClient.bottom-rtBtn.bottom;  //离底边框的距离   
   
                MoveWindow(CRect(0,0,cx,cy));                            //移动窗口   
                pWnd->MoveWindow(CRect(cx-dx-lx,cy-ly-dy,cx-dx,cy-dy));  //移动button   
   
                CDialog::OnLButtonDown(nFlags, point);   
        }

        四、设计状态下指定对话框以全屏显示
        1、手工把它拽成比如1024×768, 然后Alt+V   U
        2、在*.rc文件中修改,但是单位不一样。

        五、用MoveWindow或SetWindowPos全屏对话框
        首先计算出客户区的大小GetClientRect();
        再计算出整个窗口的大小GetWindowRect();
        然后再得到当前屏幕的大小GetSystemMetrics();
        最后根据这三个数据进行换算,当客户区为屏幕大小时窗口的位置的大小;
        计算完成后调用MoveWindow就可以了。

#11


http://www.joyvc.cn/GuiAndWindows/GuiAndWindows00044.html

VC中自动改变控件位置和大小的对话框类
 在用VC开发应用程序时,经常会要做一些可以改变大小的对话框,而这个时候就要求对话框上的控件会随着对话框大小的改变而改变自己的位置和大小。如果控件比较少,那可以在对话框的OnSize()事件里面添加代码,通过计算来调整各个控件的位置和大小;但是,如果对话框上的控件比较多的话,那这将是一件非常痛苦的事情!要是程序中又有很多可以改变大小的对话框,那一个一个的OnSize()写下来,那会使程序员崩溃的!

        为了解决这个问题,我写了一个自动改变控件位置和大小的对话框类ClxDialog。从这个类继承的对话框类,只要在OnInitDialog()里对控件做一些简单的设置,对话框上的控件就会随着对话框大小的改变而改变自己的位置和大小。 

        为了保存控件信息,我定义了一个结构: 



typedef struct _dlgControlTag 
{
  int iId; // 控件ID
  int iFlag; // 标志,表示怎样改变控件的位置或者大小
  int iPercent; // 改变值占对话框改变值的百分比
} DLGCTLINFO, *PDLGCTLINFO; 

        这里要对结构中的iFlag和iPercent进行一些解释。其中iFlag是下面的枚举值:

enum
{
  MOVEX = 0, // 控件在X方向(左右)移动
  MOVEY, // 控件在Y方向(上下)移动
  MOVEXY, // 控件在X方向和Y方向同时移动
  ELASTICX, // 控件在X方向(宽度)改变大小
  ELASTICY, // 控件在Y方向改(高度)改变大小
  ELASTICXY // 控件在X方向和Y方向同时改变大小
}; 

        iPercent表示改变值占对话框改变值的百分比。例如,一个控件的iPercent值为100,iFlag值为MOVEX,那么当对话框的宽度改变100个单位的时候,这个控件就在X方向移动100个单位;又如,一个控件的iPercent值为100,iFlag值为ELASTICXY,那么当对话框的宽度和高度分别改变100个单位的时候,控件的高度和宽度也相应的改变100个单位。

        下面是设置控件信息的函数:

BOOL SetControlProperty(PDLGCTLINFO lp, int nElements); 

        使用起来非常简单,在对话框的OnInitDialog()函数里面添加类似下面的代码就行了:

// 控件信息数组
static DLGCTLINFO dcMenuGroup[] = 
{
  {IDOK, MOVEX, 100},
  {IDCANCEL, MOVEX, 100},
  {IDC_BUTTON1, MOVEX, 50},
  {IDC_BUTTON1, MOVEY, 100},
  {IDC_EDIT1, ELASTICX, 100},
  {IDC_EDIT2, ELASTICX, 50},
  {IDC_EDIT3, ELASTICX, 50},
  {IDC_EDIT3, MOVEX, 50},
  {IDC_EDIT4, ELASTICY, 100},
  {IDC_EDIT5, ELASTICX, 100},
  {IDC_EDIT5, ELASTICY, 50},
  {IDC_EDIT6, ELASTICX, 100},
  {IDC_EDIT6, ELASTICY, 50},
  {IDC_EDIT6, MOVEY, 50},
};

// 设置控件信息
SetControlProperty(dcMenuGroup, sizeof(dcMenuGroup)/sizeof(DLGCTLINFO)); 

        下面就是使用上面这段代码的对话框改变大小前后的效果图:


 

   

           对两张截图的比较我们可以很容易的理解上面那段代码。

        我还提供了一个函数:

void ShowSizeIcon(BOOL bShow = TRUE); 


        来设置是否显示对话框右下角表示可以改变大小的图标。这个图标是从系统中读取的,我上面的截图是Windows2000下的,在WindowsXP中就会自动变成XP风格的。

        好了,闲话不多说了,下面贴出该对话框类ClxDialog的源代码,里面有详细的注释:



lxDialog.h文件:

/////////////////////////////////////////////////////////////////////////////////////
// 自动改变控件位置和大小的对话框类
// 文件名:lxDialog.h
// 作者:StarLee(coolstarlee@sohu.com)
/////////////////////////////////////////////////////////////////////////////////////

class ClxDialog : public CDialog
{
public:
ClxDialog(UINT nID, CWnd* pParent = NULL);

typedef struct _dlgControlTag 
{
  int iId;
  int iFlag;
  int iPercent;
} DLGCTLINFO, *PDLGCTLINFO;

enum
{
  MOVEX = 0,
  MOVEY,
  MOVEXY,
  ELASTICX,
  ELASTICY,
  ELASTICXY
};

// 设置控件信息
BOOL SetControlProperty(PDLGCTLINFO lp, int nElements);

// 是否在对话框右下角显示表示可改变大小的图标
void ShowSizeIcon(BOOL bShow = TRUE);

protected:
  virtual BOOL OnInitDialog();
  afx_msg void OnSize(UINT nType, int cx, int cy);
  afx_msg void OnSizing(UINT nSide, LPRECT lpRect);
  DECLARE_MESSAGE_MAP()

private:
  int m_iClientWidth; // 对话框client区域的宽度
  int m_iClientHeight; // 对话框client区域的高度
  int m_iMinWidth; // 对话框的最小宽度
  int m_iMinHeight; // 对话框的最小高度
  PDLGCTLINFO m_pControlArray; // 控件信息数组指针
  int m_iControlNumber; // 设置控件信息的控件个数
  BOOL m_bShowSizeIcon; // 是否显示表示可改变大小的图标
  CStatic m_wndSizeIcon; // 放图标的静态控件
  // 保存图标的bitmap
  CBitmap m_bmpSizeIcon; 
  BITMAP m_bitmap; 
};

lxDialog.cpp文件:

//////////////////////////////////////////////////////////////////////
// 自动改变控件位置和大小的对话框类
// 文件名:lxDialog.cpp
// 作者:StarLee(coolstarlee@sohu.com)
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "lxDialog.h"

// 表示可改变大小的图标ID
#ifndef OBM_SIZE
#define OBM_SIZE 32766
#endif

ClxDialog::ClxDialog(UINT nID, CWnd* pParent /*=NULL*/)
: CDialog(nID, pParent)
, m_iClientWidth(0)
, m_iClientHeight(0)
, m_iMinWidth(0)
, m_iMinHeight(0)
, m_pControlArray(NULL)
, m_iControlNumber(0)
, m_bShowSizeIcon(TRUE)
{}

BEGIN_MESSAGE_MAP(ClxDialog, CDialog)
  ON_WM_SIZE()
  ON_WM_SIZING()
END_MESSAGE_MAP()

BOOL ClxDialog::OnInitDialog()
{
  CDialog::OnInitDialog();

  // 设置对话框为可变大小的
  ModifyStyle(0, WS_SIZEBOX);

  // 以对话框的初始大小作为对话框的宽度和高度的最小值
  CRect rectDlg;
  GetWindowRect(rectDlg);
  m_iMinWidth = rectDlg.Width();
  m_iMinHeight = rectDlg.Height();

  // 得到对话框client区域的大小 
  CRect rectClient;
  GetClientRect(rectClient);
  m_iClientWidth = rectClient.Width();
  m_iClientHeight = rectClient.Height();

  // Load图标
  m_bmpSizeIcon.LoadOEMBitmap(OBM_SIZE);
  m_bmpSizeIcon.GetBitmap(&m_bitmap);

  // 创建显示图标的静态控件并放在对话框右下角
  m_wndSizeIcon.Create(NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP, CRect(0, 0, m_bitmap.bmWidth, m_bitmap.bmHeight), this, 0);
  m_wndSizeIcon.SetBitmap(m_bmpSizeIcon);
  m_wndSizeIcon.MoveWindow(m_iClientWidth - m_bitmap.bmWidth, m_iClientHeight - m_bitmap.bmHeight, m_bitmap.bmWidth, m_bitmap.bmHeight);

  // 显示图标
  m_wndSizeIcon.ShowWindow(m_bShowSizeIcon);

  return TRUE;
}

void ClxDialog::OnSize(UINT nType, int cx, int cy) 
{
  CDialog::OnSize(nType, cx, cy);

  // 对话框宽度和高度的增量 
  int iIncrementX = cx - m_iClientWidth;
  int iIncrementY = cy - m_iClientHeight;

  // 最小化时增量为0
  if (nType == SIZE_MINIMIZED)
  {
   iIncrementX = iIncrementY = 0;
  }

  for (int i = 0; i < m_iControlNumber; i++)
  {
   CWnd *pWndCtrl = NULL;

   int iId = m_pControlArray[i].iId;
   int iFlag = m_pControlArray[i].iFlag;
   int iPercent = m_pControlArray[i].iPercent;

   // 无效值
   if ((iPercent < 0) || (iPercent > 100))
    continue;

   // 得到控件指针
   pWndCtrl = GetDlgItem(iId);
   if ((NULL != pWndCtrl) && IsWindow(pWndCtrl->GetSafeHwnd()))
   {
    CRect rectCtrl;
    pWndCtrl->GetWindowRect(rectCtrl);

    ScreenToClient(rectCtrl);

    int iLeft = rectCtrl.left;
    int iTop = rectCtrl.top;
    int iWidth = rectCtrl.Width();
    int iHeight = rectCtrl.Height();

    switch (iFlag)
    {
     case MOVEX: // X方向移动
      iLeft += (iIncrementX * iPercent / 100);
      break;

     case MOVEY: // Y方向移动
      iTop += (iIncrementY * iPercent / 100);
      break;

     case MOVEXY: // X方向和Y方向同时移动
      iLeft += (iIncrementX * iPercent / 100);
      iTop += (iIncrementY * iPercent / 100);
      break;

     case ELASTICX: // X方向改变大小
      iWidth += (iIncrementX * iPercent / 100);
      break;

     case ELASTICY: // Y方向改变大小
      iHeight += (iIncrementY * iPercent / 100);
      break;

     case ELASTICXY: // X方向和Y方向同时改变大小
      iWidth += (iIncrementX * iPercent / 100);
      iHeight += (iIncrementY * iPercent / 100);
      break;

     default:
      ;
    }

    // 把控件移动到新位置
    pWndCtrl->MoveWindow(iLeft, iTop, iWidth, iHeight);
   }
  }

  // 把图标移动到对话框右下角
  if (IsWindow(m_wndSizeIcon.GetSafeHwnd()))
   m_wndSizeIcon.MoveWindow(cx - m_bitmap.bmWidth, cy - m_bitmap.bmHeight, m_bitmap.bmWidth, m_bitmap.bmHeight);

  // 记录对话框client区域的大小
  if (nType != SIZE_MINIMIZED)
  {
   m_iClientWidth = cx;
   m_iClientHeight = cy;
  }
}

void ClxDialog::OnSizing(UINT nSide, LPRECT lpRect)
{
  CDialog::OnSizing(nSide, lpRect);

  // 对话框不能小于初始大小

  int iWidth = lpRect->right - lpRect->left;
  int iHeight = lpRect->bottom - lpRect->top;

  if (iWidth <= m_iMinWidth)
   lpRect->right = lpRect->left + m_iMinWidth;

  if(iHeight <= m_iMinHeight)
   lpRect->bottom = lpRect->top + m_iMinHeight;
}

BOOL ClxDialog::SetControlProperty(PDLGCTLINFO lp, int nElements)
{
  // 设置控件数组信息

  if (NULL == lp)
   return FALSE;

  if (nElements <= 0)
   return FALSE;

  m_pControlArray = lp;
  m_iControlNumber = nElements;

  return TRUE;
}

void ClxDialog::ShowSizeIcon(BOOL bShow /*=NULL*/)
{
  m_bShowSizeIcon = bShow;

#12


引用 4 楼 FireBirdCN 的回复:
以上三楼 正是偶想说的 
^_^ 
每次OnSize 获得一个CRect 
根据这个CRect 来确定 那些控件的位置 MoveWindow 或者 SetWindowpos

还有10、11楼。。。
还能说什么。。。

#13


11楼得同志,能否说的再具体点??照你的步骤做了,但是还是调试不通
\VC++\111\111Dlg.cpp(121) : error C2146: syntax error : missing ';' before identifier 'dcMenuGroup'
VC++\111\111Dlg.cpp(121) : error C2065: 'dcMenuGroup' : undeclared identifier
\VC++\111\111Dlg.cpp(121) : error C2059: syntax error : ']'
\VC++\111\111Dlg.cpp(122) : error C2143: syntax error : missing ';' before '{'
\VC++\111\111Dlg.cpp(123) : error C2065: 'MOVEX' : undeclared identifier
\VC++\111\111Dlg.cpp(123) : error C2143: syntax error : missing ';' before '}'
\VC++\111\111Dlg.cpp(128) : error C2065: 'SetControlProperty' : undeclared identifier
执行 cl.exe 时出错.

111.exe - 1 error(s), 0 warning(s)

#14


谢谢了各位

#15


如何再详细些就更好了

#16


引用 15 楼  的回复:
如何再详细些就更好了


这位仁兄和我有一样的需求呀~

#17


scq2099yt说得很好,我也正在学习这个,受教了。 如何使控件随对话框大小变化而调整大小和位置?

#18


怎么示例图片看不到呢?

#1


响应WM_SIZE,调用MoveWindow调整控件位置和大小

#2


void CXTest2Dlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
//将窗口移动到合适位置和大小
CRect rc,rc0,rc1;
GetClientRect(&rc0);//先取得整个对话框的大小及位置
//设置Tab控件位置
rc1.top=rc0.top;
rc1.left=rc0.left+1;
rc1.bottom=rc0.bottom-30;
rc1.right=rc0.right-1;
if(GetDlgItem(IDC_TAB1)!=NULL)
{
GetDlgItem(IDC_TAB1)->MoveWindow(&rc1);
}

//设置时钟位置
rc1.top=rc0.bottom-20;
rc1.left=rc0.left+5;
rc1.bottom=rc0.bottom;
rc1.right=rc0.left+160;
if(GetDlgItem(IDC_CLOCKTEST)!=NULL)
{
GetDlgItem(IDC_CLOCKTEST)->MoveWindow(&rc1);
}
//设置关闭按钮位置
rc1.top=rc1.top-5;
rc1.left=rc0.right-200;
rc1.bottom=rc1.bottom;
rc1.right=rc0.right-120;
if(GetDlgItem(IDOK)!=NULL)
{
GetDlgItem(IDOK)->MoveWindow(&rc1);
}
//设置取消按钮位置
rc1.left=rc0.right-100;
rc1.right=rc0.right-20;
if(GetDlgItem(IDCANCEL)!=NULL)
{
GetDlgItem(IDCANCEL)->MoveWindow(&rc1);
}

//将三个对话框资源定位到Tab控件中
if(GetDlgItem(IDC_TAB1)!=NULL)
{
GetDlgItem(IDC_TAB1)->GetClientRect(&rc);
rc1.top=rc.top+20;
rc1.left=rc.left+1;
rc1.bottom=rc.bottom-10;
rc1.right=rc.right-1;
tab1.MoveWindow(&rc1);
tab2.MoveWindow(&rc1);
tab3.MoveWindow(&rc1);
//将三个对话框资源中的控件随对话框大小变化
GetDlgItem(IDC_MSGINFO)->MoveWindow(&rc1);//移动第一个
rc1.bottom=rc.bottom-35;//第二个及第三个底部留出按钮位置
GetDlgItem(IDC_BNSLIST)->MoveWindow(&rc1);
GetDlgItem(IDC_MSGERRINFO)->MoveWindow(&rc1);

}
}
红色部分的代码出错

#3


基本的做法就是响应 wm_size消息,按照窗口大小比例调整控件的位置和大小

#4


以上三楼 正是偶想说的 
^_^
每次OnSize 获得一个CRect 
根据这个CRect 来确定 那些控件的位置 MoveWindow 或者 SetWindowpos

#5


google seach 

CResizeDialog

good luck

#6


tab1.GetClientRect(&rc1);
tab1.GetDlgItem(IDC_MSGINFO)->MoveWindow(&rc1);//移动第一个 
rc1.bottom=rc.bottom-35;//第二个及第三个底部留出按钮位置 
tab2.GetDlgItem(IDC_BNSLIST)->MoveWindow(&rc1); 
tab3.GetDlgItem(IDC_MSGERRINFO)->MoveWindow(&rc1); 

#7


控件的大小最好设置成窗口的 百分之几 这样的话 就可以根据窗口的大小随时调整了

#8


这个就得自己写了,对控件MoveWindow、SetWindowpos。

#9


是否可以响应WM_WINDOWPOSCHANGED消息?对话框的大小位置改变后再据此来调整控件?

#10


http://www.joyvc.cn/GuiAndWindows/GuiAndWindows00040.html

一、简单对话框全屏显示方法
        在OnInitDialog()中任意加入:
        1、ModifyStyle(WS_CAPTION,0,0);   //如果不想去掉标题栏,去掉该句。
                SendMessage(WM_SYSCOMMAND,SC_MAXIMIZE,0); 
        2、ShowWindow(SW_SHOWMAXIMIZED);   
        二、复杂一点的对话框全屏显示方法,随屏幕的分辩率而调节
        void CMainFrame::OnFullScreen()     
        {
                GetWindowPlacement(&m_OldWndPlacement);     
                CRect WindowRect;     
                GetWindowRect(&WindowRect);     
                CRect ClientRect;     
                RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &ClientRect);     
                ClientToScreen(&ClientRect); 
    
                //获取屏幕的分辨率     
                int nFullWidth=GetSystemMetrics(SM_CXSCREEN);     
                int nFullHeight=GetSystemMetrics(SM_CYSCREEN);
     
                //将除控制条外的客户区全屏显示到从(0,0)到(nFullWidth, nFullHeight)区域, 
                //将(0,0)和(nFullWidth, nFullHeight)两个点外扩充原窗口和除控制条之外的
                //客户区位置间的差值, 就得到全屏显示的窗口位置     
                m_FullScreenRect.left=WindowRect.left-ClientRect.left;     
                m_FullScreenRect.top=WindowRect.top-ClientRect.top;     
                m_FullScreenRect.right=WindowRect.right-ClientRect.right+nFullWidth;     
                m_FullScreenRect.bottom=WindowRect.bottom-ClientRect.bottom+nFullHeight;     
                m_bFullScreen=TRUE;   //设置全屏显示标志为TRUE
     
                //进入全屏显示状态     
                WINDOWPLACEMENT wndpl;     
                wndpl.length=sizeof(WINDOWPLACEMENT);     
                wndpl.flags=0;     
                wndpl.showCmd=SW_SHOWNORMAL;     
                wndpl.rcNormalPosition=m_FullScreenRect;     
                SetWindowPlacement(&wndpl);
        } 

        三、对话框全屏及按钮控件移到相应位置
        void CXXXDlg::OnLButtonDown(UINT nFlags, CPoint point)     
        {                     
                int cx=::GetSystemMetrics(SM_CXSCREEN);   
                int cy=::GetSystemMetrics(SM_CYSCREEN);   
    
                CRect rtClient,rtBtn;   
                CWnd  *pWnd=GetDlgItem(IDC_BUTTON);   
    
                GetClientRect(&rtClient);             //获得对话框客户区屏幕坐标   
                ClientToScreen(&rtClient);            //映射为屏幕坐标   
                pWnd->GetWindowRect(&rtBtn);          //获得button屏幕坐标   
   
                int lx=rtBtn.Width();                 //button长度   
                int ly=rtBtn.Height();                //button高度   
                int dx=rtClient.right-rtBtn.right;    //离右边框的距离   
                int dy=rtClient.bottom-rtBtn.bottom;  //离底边框的距离   
   
                MoveWindow(CRect(0,0,cx,cy));                            //移动窗口   
                pWnd->MoveWindow(CRect(cx-dx-lx,cy-ly-dy,cx-dx,cy-dy));  //移动button   
   
                CDialog::OnLButtonDown(nFlags, point);   
        }

        四、设计状态下指定对话框以全屏显示
        1、手工把它拽成比如1024×768, 然后Alt+V   U
        2、在*.rc文件中修改,但是单位不一样。

        五、用MoveWindow或SetWindowPos全屏对话框
        首先计算出客户区的大小GetClientRect();
        再计算出整个窗口的大小GetWindowRect();
        然后再得到当前屏幕的大小GetSystemMetrics();
        最后根据这三个数据进行换算,当客户区为屏幕大小时窗口的位置的大小;
        计算完成后调用MoveWindow就可以了。

#11


http://www.joyvc.cn/GuiAndWindows/GuiAndWindows00044.html

VC中自动改变控件位置和大小的对话框类
 在用VC开发应用程序时,经常会要做一些可以改变大小的对话框,而这个时候就要求对话框上的控件会随着对话框大小的改变而改变自己的位置和大小。如果控件比较少,那可以在对话框的OnSize()事件里面添加代码,通过计算来调整各个控件的位置和大小;但是,如果对话框上的控件比较多的话,那这将是一件非常痛苦的事情!要是程序中又有很多可以改变大小的对话框,那一个一个的OnSize()写下来,那会使程序员崩溃的!

        为了解决这个问题,我写了一个自动改变控件位置和大小的对话框类ClxDialog。从这个类继承的对话框类,只要在OnInitDialog()里对控件做一些简单的设置,对话框上的控件就会随着对话框大小的改变而改变自己的位置和大小。 

        为了保存控件信息,我定义了一个结构: 



typedef struct _dlgControlTag 
{
  int iId; // 控件ID
  int iFlag; // 标志,表示怎样改变控件的位置或者大小
  int iPercent; // 改变值占对话框改变值的百分比
} DLGCTLINFO, *PDLGCTLINFO; 

        这里要对结构中的iFlag和iPercent进行一些解释。其中iFlag是下面的枚举值:

enum
{
  MOVEX = 0, // 控件在X方向(左右)移动
  MOVEY, // 控件在Y方向(上下)移动
  MOVEXY, // 控件在X方向和Y方向同时移动
  ELASTICX, // 控件在X方向(宽度)改变大小
  ELASTICY, // 控件在Y方向改(高度)改变大小
  ELASTICXY // 控件在X方向和Y方向同时改变大小
}; 

        iPercent表示改变值占对话框改变值的百分比。例如,一个控件的iPercent值为100,iFlag值为MOVEX,那么当对话框的宽度改变100个单位的时候,这个控件就在X方向移动100个单位;又如,一个控件的iPercent值为100,iFlag值为ELASTICXY,那么当对话框的宽度和高度分别改变100个单位的时候,控件的高度和宽度也相应的改变100个单位。

        下面是设置控件信息的函数:

BOOL SetControlProperty(PDLGCTLINFO lp, int nElements); 

        使用起来非常简单,在对话框的OnInitDialog()函数里面添加类似下面的代码就行了:

// 控件信息数组
static DLGCTLINFO dcMenuGroup[] = 
{
  {IDOK, MOVEX, 100},
  {IDCANCEL, MOVEX, 100},
  {IDC_BUTTON1, MOVEX, 50},
  {IDC_BUTTON1, MOVEY, 100},
  {IDC_EDIT1, ELASTICX, 100},
  {IDC_EDIT2, ELASTICX, 50},
  {IDC_EDIT3, ELASTICX, 50},
  {IDC_EDIT3, MOVEX, 50},
  {IDC_EDIT4, ELASTICY, 100},
  {IDC_EDIT5, ELASTICX, 100},
  {IDC_EDIT5, ELASTICY, 50},
  {IDC_EDIT6, ELASTICX, 100},
  {IDC_EDIT6, ELASTICY, 50},
  {IDC_EDIT6, MOVEY, 50},
};

// 设置控件信息
SetControlProperty(dcMenuGroup, sizeof(dcMenuGroup)/sizeof(DLGCTLINFO)); 

        下面就是使用上面这段代码的对话框改变大小前后的效果图:


 

   

           对两张截图的比较我们可以很容易的理解上面那段代码。

        我还提供了一个函数:

void ShowSizeIcon(BOOL bShow = TRUE); 


        来设置是否显示对话框右下角表示可以改变大小的图标。这个图标是从系统中读取的,我上面的截图是Windows2000下的,在WindowsXP中就会自动变成XP风格的。

        好了,闲话不多说了,下面贴出该对话框类ClxDialog的源代码,里面有详细的注释:



lxDialog.h文件:

/////////////////////////////////////////////////////////////////////////////////////
// 自动改变控件位置和大小的对话框类
// 文件名:lxDialog.h
// 作者:StarLee(coolstarlee@sohu.com)
/////////////////////////////////////////////////////////////////////////////////////

class ClxDialog : public CDialog
{
public:
ClxDialog(UINT nID, CWnd* pParent = NULL);

typedef struct _dlgControlTag 
{
  int iId;
  int iFlag;
  int iPercent;
} DLGCTLINFO, *PDLGCTLINFO;

enum
{
  MOVEX = 0,
  MOVEY,
  MOVEXY,
  ELASTICX,
  ELASTICY,
  ELASTICXY
};

// 设置控件信息
BOOL SetControlProperty(PDLGCTLINFO lp, int nElements);

// 是否在对话框右下角显示表示可改变大小的图标
void ShowSizeIcon(BOOL bShow = TRUE);

protected:
  virtual BOOL OnInitDialog();
  afx_msg void OnSize(UINT nType, int cx, int cy);
  afx_msg void OnSizing(UINT nSide, LPRECT lpRect);
  DECLARE_MESSAGE_MAP()

private:
  int m_iClientWidth; // 对话框client区域的宽度
  int m_iClientHeight; // 对话框client区域的高度
  int m_iMinWidth; // 对话框的最小宽度
  int m_iMinHeight; // 对话框的最小高度
  PDLGCTLINFO m_pControlArray; // 控件信息数组指针
  int m_iControlNumber; // 设置控件信息的控件个数
  BOOL m_bShowSizeIcon; // 是否显示表示可改变大小的图标
  CStatic m_wndSizeIcon; // 放图标的静态控件
  // 保存图标的bitmap
  CBitmap m_bmpSizeIcon; 
  BITMAP m_bitmap; 
};

lxDialog.cpp文件:

//////////////////////////////////////////////////////////////////////
// 自动改变控件位置和大小的对话框类
// 文件名:lxDialog.cpp
// 作者:StarLee(coolstarlee@sohu.com)
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "lxDialog.h"

// 表示可改变大小的图标ID
#ifndef OBM_SIZE
#define OBM_SIZE 32766
#endif

ClxDialog::ClxDialog(UINT nID, CWnd* pParent /*=NULL*/)
: CDialog(nID, pParent)
, m_iClientWidth(0)
, m_iClientHeight(0)
, m_iMinWidth(0)
, m_iMinHeight(0)
, m_pControlArray(NULL)
, m_iControlNumber(0)
, m_bShowSizeIcon(TRUE)
{}

BEGIN_MESSAGE_MAP(ClxDialog, CDialog)
  ON_WM_SIZE()
  ON_WM_SIZING()
END_MESSAGE_MAP()

BOOL ClxDialog::OnInitDialog()
{
  CDialog::OnInitDialog();

  // 设置对话框为可变大小的
  ModifyStyle(0, WS_SIZEBOX);

  // 以对话框的初始大小作为对话框的宽度和高度的最小值
  CRect rectDlg;
  GetWindowRect(rectDlg);
  m_iMinWidth = rectDlg.Width();
  m_iMinHeight = rectDlg.Height();

  // 得到对话框client区域的大小 
  CRect rectClient;
  GetClientRect(rectClient);
  m_iClientWidth = rectClient.Width();
  m_iClientHeight = rectClient.Height();

  // Load图标
  m_bmpSizeIcon.LoadOEMBitmap(OBM_SIZE);
  m_bmpSizeIcon.GetBitmap(&m_bitmap);

  // 创建显示图标的静态控件并放在对话框右下角
  m_wndSizeIcon.Create(NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP, CRect(0, 0, m_bitmap.bmWidth, m_bitmap.bmHeight), this, 0);
  m_wndSizeIcon.SetBitmap(m_bmpSizeIcon);
  m_wndSizeIcon.MoveWindow(m_iClientWidth - m_bitmap.bmWidth, m_iClientHeight - m_bitmap.bmHeight, m_bitmap.bmWidth, m_bitmap.bmHeight);

  // 显示图标
  m_wndSizeIcon.ShowWindow(m_bShowSizeIcon);

  return TRUE;
}

void ClxDialog::OnSize(UINT nType, int cx, int cy) 
{
  CDialog::OnSize(nType, cx, cy);

  // 对话框宽度和高度的增量 
  int iIncrementX = cx - m_iClientWidth;
  int iIncrementY = cy - m_iClientHeight;

  // 最小化时增量为0
  if (nType == SIZE_MINIMIZED)
  {
   iIncrementX = iIncrementY = 0;
  }

  for (int i = 0; i < m_iControlNumber; i++)
  {
   CWnd *pWndCtrl = NULL;

   int iId = m_pControlArray[i].iId;
   int iFlag = m_pControlArray[i].iFlag;
   int iPercent = m_pControlArray[i].iPercent;

   // 无效值
   if ((iPercent < 0) || (iPercent > 100))
    continue;

   // 得到控件指针
   pWndCtrl = GetDlgItem(iId);
   if ((NULL != pWndCtrl) && IsWindow(pWndCtrl->GetSafeHwnd()))
   {
    CRect rectCtrl;
    pWndCtrl->GetWindowRect(rectCtrl);

    ScreenToClient(rectCtrl);

    int iLeft = rectCtrl.left;
    int iTop = rectCtrl.top;
    int iWidth = rectCtrl.Width();
    int iHeight = rectCtrl.Height();

    switch (iFlag)
    {
     case MOVEX: // X方向移动
      iLeft += (iIncrementX * iPercent / 100);
      break;

     case MOVEY: // Y方向移动
      iTop += (iIncrementY * iPercent / 100);
      break;

     case MOVEXY: // X方向和Y方向同时移动
      iLeft += (iIncrementX * iPercent / 100);
      iTop += (iIncrementY * iPercent / 100);
      break;

     case ELASTICX: // X方向改变大小
      iWidth += (iIncrementX * iPercent / 100);
      break;

     case ELASTICY: // Y方向改变大小
      iHeight += (iIncrementY * iPercent / 100);
      break;

     case ELASTICXY: // X方向和Y方向同时改变大小
      iWidth += (iIncrementX * iPercent / 100);
      iHeight += (iIncrementY * iPercent / 100);
      break;

     default:
      ;
    }

    // 把控件移动到新位置
    pWndCtrl->MoveWindow(iLeft, iTop, iWidth, iHeight);
   }
  }

  // 把图标移动到对话框右下角
  if (IsWindow(m_wndSizeIcon.GetSafeHwnd()))
   m_wndSizeIcon.MoveWindow(cx - m_bitmap.bmWidth, cy - m_bitmap.bmHeight, m_bitmap.bmWidth, m_bitmap.bmHeight);

  // 记录对话框client区域的大小
  if (nType != SIZE_MINIMIZED)
  {
   m_iClientWidth = cx;
   m_iClientHeight = cy;
  }
}

void ClxDialog::OnSizing(UINT nSide, LPRECT lpRect)
{
  CDialog::OnSizing(nSide, lpRect);

  // 对话框不能小于初始大小

  int iWidth = lpRect->right - lpRect->left;
  int iHeight = lpRect->bottom - lpRect->top;

  if (iWidth <= m_iMinWidth)
   lpRect->right = lpRect->left + m_iMinWidth;

  if(iHeight <= m_iMinHeight)
   lpRect->bottom = lpRect->top + m_iMinHeight;
}

BOOL ClxDialog::SetControlProperty(PDLGCTLINFO lp, int nElements)
{
  // 设置控件数组信息

  if (NULL == lp)
   return FALSE;

  if (nElements <= 0)
   return FALSE;

  m_pControlArray = lp;
  m_iControlNumber = nElements;

  return TRUE;
}

void ClxDialog::ShowSizeIcon(BOOL bShow /*=NULL*/)
{
  m_bShowSizeIcon = bShow;

#12


引用 4 楼 FireBirdCN 的回复:
以上三楼 正是偶想说的 
^_^ 
每次OnSize 获得一个CRect 
根据这个CRect 来确定 那些控件的位置 MoveWindow 或者 SetWindowpos

还有10、11楼。。。
还能说什么。。。

#13


11楼得同志,能否说的再具体点??照你的步骤做了,但是还是调试不通
\VC++\111\111Dlg.cpp(121) : error C2146: syntax error : missing ';' before identifier 'dcMenuGroup'
VC++\111\111Dlg.cpp(121) : error C2065: 'dcMenuGroup' : undeclared identifier
\VC++\111\111Dlg.cpp(121) : error C2059: syntax error : ']'
\VC++\111\111Dlg.cpp(122) : error C2143: syntax error : missing ';' before '{'
\VC++\111\111Dlg.cpp(123) : error C2065: 'MOVEX' : undeclared identifier
\VC++\111\111Dlg.cpp(123) : error C2143: syntax error : missing ';' before '}'
\VC++\111\111Dlg.cpp(128) : error C2065: 'SetControlProperty' : undeclared identifier
执行 cl.exe 时出错.

111.exe - 1 error(s), 0 warning(s)

#14


谢谢了各位

#15


如何再详细些就更好了

#16


引用 15 楼  的回复:
如何再详细些就更好了


这位仁兄和我有一样的需求呀~

#17


scq2099yt说得很好,我也正在学习这个,受教了。 如何使控件随对话框大小变化而调整大小和位置?

#18


怎么示例图片看不到呢?