MFC改变对话框的大小,以及子控件的动态改变

无论是单文档还是基于对话框,可能更普遍的方式是接受WM_size消息,使用setWindowPos(),moveWindow()方法。

1、首先写一个示例

////////////////////////////////////////////////////////////////////////////////////
// 自动改变控件位置和大小的对话框类
// 文件名:lxDialog.h
/////////////////////////////////////////////////////////////////////////////////////
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
//////////////////////////////////////////////////////////////////////
#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;
}

 

《《《《《《《《《《《《《《《《《《《《《《《《《《《《》》》》》》》》》》》》》》》》》》》》》》》》》

2、再写一个示例,还是动态改变对话框的(基于dialog的对话框)

初始化时用来猎取每个控件的位置和大小,写一个函数是在窗口大小改变时,根据原来获得的各控件大小和位置进行等比例放大和缩小即可

一 在头文件 POINT Old;//存放对话框的宽和高。

OnInitDialog //计录宽和高。
 CRect rect;   
 GetClientRect(&rect); //取客户区大小  
 Old.x=rect.right-rect.left;
 Old.y=rect.bottom-rect.top;


二 添加 WM_SIZE消息:
 if(nType==SIZE_RESTORED||nType==SIZE_MAXIMIZED)//窗体大小发生变动。处理函数resize
 {
  resize();
 }

三 添加reseze函数
void CMy2610Dlg::resize()
{
 float fsp[2];
 POINT Newp; //获取现在对话框的大小
 CRect recta;   
 GetClientRect(&recta); //取客户区大小  
 Newp.x=recta.right-recta.left;
 Newp.y=recta.bottom-recta.top;
 fsp[0]=(float)Newp.x/Old.x;
 fsp[1]=(float)Newp.y/Old.y;
 CRect Rect;
 int woc;
 CPoint OldTLPoint,TLPoint; //左上角
 CPoint OldBRPoint,BRPoint; //右下角
 HWND hwndChild=::GetWindow(m_hWnd,GW_CHILD); //列出所有控件  
 while(hwndChild)   
 {   
  woc=::GetDlgCtrlID(hwndChild);//取得ID
  GetDlgItem(woc)->GetWindowRect(Rect);  
  ScreenToClient(Rect);  
  OldTLPoint = Rect.TopLeft();  
  TLPoint.x = long(OldTLPoint.x*fsp[0]);  
  TLPoint.y = long(OldTLPoint.y*fsp[1]);  
  OldBRPoint = Rect.BottomRight();  
  BRPoint.x = long(OldBRPoint.x *fsp[0]);  
  BRPoint.y = long(OldBRPoint.y *fsp[1]);  
  Rect.SetRect(TLPoint,BRPoint);  
  GetDlgItem(woc)->MoveWindow(Rect,TRUE);
  hwndChild=::GetWindow(hwndChild, GW_HWNDNEXT);   
 }
 Old=Newp;
}
注:若只要最大化,不用拖动可以不用设置下面的
需要拖动的需要设置
中文版:右击对话框属性--样式--边框(调整大小)
英文版:Styles--Border--选择Risizing,   

说明:

如果你窗口中有comboBox这种高度只读的控件,改变窗口大小后下拉框会拉不开,这是需要在遍历控件时加判断,如果是comboBox,就不要改变BRPoint.y值,也就是不要改变高度。

 

《《《《《《《《《《《《《《《《《《《《《》》》》》》》》》》》》》》》》》》》》》》》》

3、窗口最大化

vc++ 窗口最大化方法

一般的做法是在 C**App::InitInstance()中,修改成这样:
{
//...
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
m_pMainWnd->UpdateWindow();
//...
}
或者,还在 CMainFrame::PreCreateWindow(CREATESTRUCT& cs)中,添加:
{
//...
cs.style |= WS_MAXIMIZE;
//...
}

这种做法能产生窗口最大化,但效果是显示的时候窗口从普通大小"闪"到最大化。还有的做法,是先将窗口隐藏,然后再最大化。那么怎样使窗口正常一开始出现就最大化?看看下面的流程,从 C**App::InitInstance()中的ProcessShellCommand(...)开始:
{
//...
//ProcessShellCommand中第一次显示了窗口
if (!ProcessShellCommand(cmdInfo))
  return FALSE;
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
m_pMainWnd->UpdateWindow();
//...
}


->CWinApp::ProcessShellCommand  
->AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)  
//如果你自己处理了ID_FILE_NEW要调用CWinApp::OnFileNew()
->CWinApp::OnFileNew()
->CDocManager::OnFileNew()  
->CSingleDocTemplate::OpenDocumentFile //当前文档模板初始化
->CSingleDocTemplate::CreateNewDocument //创建文档
//加载资源并创建主窗口(顺便创建视图),但没显示
->CSingleDocTemplate::CreateNewFrame  
->CFrameWnd::InitialUpdateFrame
{
//...
int nCmdShow = -1; // default
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->m_pMainWnd == this)
{
  nCmdShow = pApp->m_nCmdShow; // use the parameter from WinMain
  pApp->m_nCmdShow = -1; // set to default after first time
}
ActivateFrame(nCmdShow); //在这里第一次显示窗口
//...
}
->CFrameWnd::ActivateFrame(int nCmdShow)
// nCmdShow is the normal show mode this frame should be in
{
// translate default nCmdShow (-1)
if (nCmdShow == -1)
{
  if (!IsWindowVisible())
  nCmdShow = SW_SHOWNORMAL;
  else if (IsIconic())
  nCmdShow = SW_RESTORE;
}

// bring to top before showing
BringToTop(nCmdShow);

if (nCmdShow != -1)
{
  // show the window as specified
  ShowWindow(nCmdShow); //第一次显示窗口

  // and finally, bring to top after showing
  BringToTop(nCmdShow);
}
}
->***

从上面可以看出,CWinApp::ProcessShellCommand函数创建了窗口并显示,这是窗口第一次显示,先于:
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
m_pMainWnd->UpdateWindow();


怎么解决问题? 让窗口第一次显示就最大化?

CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);

// Dispatch commands specified on the command line
//在ParseCommandLine之后,ProcessShellCommand之前,添加这句!!!
m_nCmdShow = SW_SHOWMAXIMIZED;  
if (!ProcessShellCommand(cmdInfo))
  return FALSE;

// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
m_pMainWnd->UpdateWindow();
《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《》》》》》》》》》》

用CWnd类的函数MoveWindow()或SetWindowPos()可以改变控件的大小和位置。

void MoveWindow(int x,int y,int nWidth,int nHeight);
void MoveWindow(LPCRECT lpRect);
第一种用法需给出控件新的坐标和宽度、高度;
第二种用法给出存放位置的CRect对象;
例:
CWnd *pWnd;
pWnd = GetDlgItem( IDC_EDIT1 );    //获取控件指针,IDC_EDIT1为控件ID号
pWnd->MoveWindow( CRect(0,0,100,100) );    //在窗口左上角显示一个宽100、高100的编辑控件

SetWindowPos()函数使用更灵活,多用于只修改控件位置而大小不变或只修改大小而位置不变的情况:
BOOL SetWindowPos(const CWnd* pWndInsertAfter,int x,int y,int cx,int cy,UINT nFlags);
第一个参数我不会用,一般设为NULL;
x、y控件位置;cx、cy控件宽度和高度;
nFlags常用取值:
SWP_NOZORDER:忽略第一个参数;
SWP_NOMOVE:忽略x、y,维持位置不变;
SWP_NOSIZE:忽略cx、cy,维持大小不变;
例:
CWnd *pWnd;
pWnd = GetDlgItem( IDC_BUTTON1 );    //获取控件指针,IDC_BUTTON1为控件ID号
pWnd->SetWindowPos( NULL,50,80,0,0,SWP_NOZORDER | SWP_NOSIZE );    //把按钮移到窗口的(50,80)处
pWnd = GetDlgItem( IDC_EDIT1 );
pWnd->SetWindowPos( NULL,0,0,100,80,SWP_NOZORDER | SWP_NOMOVE );    //把编辑控件的大小设为(100,80),位置不变
pWnd = GetDlgItem( IDC_EDIT1 );
pWnd->SetWindowPos( NULL,0,0,100,80,SWP_NOZORDER );    //编辑控件的大小和位置都改变
以上方法也适用于各种窗口。

MFC改变对话框的大小,以及子控件的动态改变 - thisisleft - give me a hug!  

<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

4、MFC教程

http://www.vczx.com/tutorial/mfc/mfc.php

  

你可能感兴趣的:(null,文档,mfc,dialog,float,button)