关于动态改变控件大小的一点不同的看法(转)

来源:互联网 发布:js给变量赋值 编辑:程序博客网 时间:2024/06/05 19:15

原文:http://www.huarw.com/program/vc/vc01/200804/1538412.html

 

关于动态改变控件大小的一点不同的看法  

   

 

编程论坛(hur.cn)发表于:2008-04-14 12:14:05 楼主

 

看了论坛上很多关于动态改变EDIT控件大小的帖子,基本上都说得很简单,重载WM_SIZE,用GetDlgItem(IDC_EDIT)->MoveWindow(CRect);
可以我用了却不行,我写了一个对话框程序,在对话框上有一个编辑框,我在对话框的OnSize函数里面用MoveWindow,编译没有错误,可每次运行时都要出错,在众多的帖子上没有人说会出错啊,我只好改变了用法,代码如下:
void CTelecomDlg::OnSize(UINT nType, int cx, int cy) 
{
CDialog::OnSize(nType, cx, cy);

// TODO: Add your message handler code here
try
{
GetDlgItem(IDC_RICHEDIT)->MoveWindow(0,0,cx,cy);   
}
catch(...)
{
AfxMessageBox("OnSize fail");
return;   
}
}
每次运行程序时都会出现异常,显示"OnSize fail",以后再改变窗体大小时就不会出现异常,编辑框也正常地动态改变了,进一步跟踪发现,nType的值在每次运行时为0,最小化时为1,最大化时为2,还原时也为0;如果在加一个if( nType != 0 )判断语句,当nType不为0时才执行MoveWindow,那运行时倒是正常了,不会出现异常,可最小化后还原时又来问题了,呵呵,编辑框“不见了”,因为没有执行MoveWindow,看来这样不行。
总结:
在开始运行程序时不应该重载WM_SIZE,和执行MoveWindow,(也不知道对不对,望指正)应该有其它更好的方法解决,我的方法第次都要抛出异常也不是个事啊,明知有异常而不解决就不叫异常了,应该叫错误。
请各位指点一下,谢谢。
(也请各位大虾以后能说得更清楚一点,很容易误导人的,难道是因为这种小问题不是问题?那可苦了我这只菜鸟)

编程论坛(hur.cn)发表于:2008-04-14 12:18:311楼 得分:6

 

第一次运行OnSize时,对话框的句柄还没有产生(通过调试可以判断出来),因此,需要先判断m_hWnd是否为空,为空则不处理。

  

编程论坛(hur.cn)发表于:2008-04-14 12:25:352楼 得分:6

 

如LS 

我一般这么写

if(m_edIT)
{
MoveWindow(rect);
}

 编程论坛(hur.cn)发表于:2008-04-14 13:06:153楼 得分:2

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 i  = rectCtrl.top; 
   int iWidth = rectCtrl.Width(); 
   int iHeight = rectCtrl.Height(); 

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

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

    cASE MOVEXY: // X方向和Y方向同时移动 
     iLeft += (iIncrementX * iPercent / 100); 
     i  += (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, i , 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 =&nbsp;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; 

http://blog.csdn.NET/scq2099yt/archive/2008/03/12/2174124.ASPx 

 

编程论坛(hur.cn)发表于:2008-04-14 13:56:484楼 得分:6

 

一楼大侠说的很清楚了

基本上都说得很简单,重载WM_SIZE,用GetDlgItem(IDC_EDIT)->MoveWindow(CRect); 
在MoveWindow前要加个窗口是否创建的判断,因为窗口创建前有一次WM_SIZE消息的响应,这时候GetDlgITem返回肯定空

 

 编程论坛(hur.cn)发表于:2008-04-14 17:26:395楼 得分:0

 

收到,谢谢各位
在MoveWindow前要加个窗口是否创建的判断
要是以前的帖子都

 

有这句话,我这个菜鸟也不用再开这个帖了

 

 

 

 

 

编程论坛(hur.cn)发表于:2008-04-14 19:40:406楼 得分:0

 

if( GetDlgItem(IDC_RICHEDIT) )
    GetDlgItem(IDC_RICHEDIT)->MoveWindow(10, 10, cx-20, cy-20);

 

 编程论坛(hur.cn)发表于:2008-04-14 19:43:107楼 得分:0

 

if( this->m_hWnd )
    GetDlgItem(IDC_RICHEDIT)->MoveWindow(10, 10, cx-20, cy-20);
这种方法好像不行,第一次运行时this->m_hWnd就不为空了


欢迎转载,但请保留出处,本文章转自[华软网] 原文链接:http://www.huarw.com/program/vc/vc01/200804/1538412_9.html