65.9K
CodeProject 正在变化。 阅读更多。
Home

创建可移动的子窗口控件

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.47/5 (5投票s)

2007年9月25日

CPOL

1分钟阅读

viewsIcon

23860

downloadIcon

508

一个关于构建可在运行时由用户移动的 Windows 控件的教程。

引言

我遇到了很多关于“如何在对话框上制作可移动控件”和“如何在运行时制作一组可移动控件”的疑问。 这里尝试以最简单的形式实现相同的功能; 但是,可以根据需要进行修改。

Screenshot - Position1.jpg

Screenshot - Position2.jpg

背景

按照 Windows 预定义的行为,我们可以使用对话框/框架窗口的标题栏在运行时移动它们。 有时您可能想要移动没有标题栏的控件/一组控件。 这里的示例代码解决了这个问题。

使用代码

该代码是使用 Microsoft Visual Studio 6.0 编写和编译的。

使用 Windows 的对话框布局编辑器将控件放置在对话框上。

Screenshot - LayoutEditor.jpg

您可以根据您的要求将成员变量与这些控件关联起来

// MovableTrialDlg.h
CStatic m_staticMovable;
CEdit   m_editMovable;

在类 CMovableTrialDlg 中定义额外的成员变量。

// MovableTrialDlg.h
bool m_bMoving;

请在您的代码中包含 PreTranslateMessage()

// MovableTrialDlg.h
virtual BOOL PreTranslateMessage(MSG* pMsg);

PreTranslateMessage() 对需要移动的控件执行所需的操作。

BOOL CMovableTrialDlg::PreTranslateMessage(MSG* pMsg) 
{
 // TODO: Add your specialized code here and/or call the base class
 if(pMsg->hwnd == m_editMovable.m_hWnd)
 {
  if(pMsg->message == WM_LBUTTONUP)
  {
   OnMovableStaticLButtonUp(pMsg);
  }
  if(pMsg->message == WM_LBUTTONDOWN)
  {
   OnMovableStaticLButtonDown(pMsg);
  }
  if(pMsg->message == WM_MOUSEMOVE)
  {
   OnMovableStaticMouseMove(pMsg);
  }
 }
 return CDialog::PreTranslateMessage(pMsg);
}

当鼠标移动且移动窗口的状态 m_bMovingtrue 时,通过更改控件的窗口位置来执行移动。

void CMovableTrialDlg::OnMovableStaticMouseMove(MSG* pMsg)
{
 if(m_bMoving == false)
  return;
 WINDOWPLACEMENT wp;
 ::GetWindowPlacement(m_editMovable.m_hWnd, &wp);
 int nXDiff = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
 int nYDiff = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
 POINT pt = pMsg->pt;
 ScreenToClient(&pt);
 wp.rcNormalPosition.left  = pt.x - 5;
 wp.rcNormalPosition.top   = pt.y - 5;
 wp.rcNormalPosition.right = wp.rcNormalPosition.left + nXDiff;
 wp.rcNormalPosition.bottom= wp.rcNormalPosition.top + nYDiff;
 ::SetWindowPlacement(m_editMovable.m_hWnd, &wp);
 ::GetWindowPlacement(m_staticMovable.m_hWnd, &wp);
 nXDiff = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
 nYDiff = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
 pt = pMsg->pt;
 ScreenToClient(&pt);
 wp.rcNormalPosition.left  = pt.x - 5;
 wp.rcNormalPosition.top   = pt.y - nYDiff - 5;
 wp.rcNormalPosition.right = wp.rcNormalPosition.left + nXDiff;
 wp.rcNormalPosition.bottom= wp.rcNormalPosition.top + nYDiff;
 ::SetWindowPlacement(m_staticMovable.m_hWnd, &wp);
 m_editMovable.Invalidate();
 m_staticMovable.Invalidate();
}

一旦鼠标左键按下事件发生在编辑控件上,将移动状态 m_bMoving 设置为 true

void CMovableTrialDlg::OnMovableStaticLButtonDown(MSG* pMsg)
{
 m_bMoving = true;
}

类似地,当鼠标左键抬起时,将移动状态 m_bMoving 更改为 false

void CMovableTrialDlg::OnMovableStaticLButtonUp(MSG* pMsg)
{
 m_bMoving = false;
}

历史

我将提供代码,以便控件组看起来像一个带有非 MDI 框架/对话框的子容器,并且可以使用标题栏进行移动。 标题栏将被模拟。

© . All rights reserved.