我不知道在这里向你展示什么代码。我的MFC应用程序中有一个CDialogEx
派生资源:
如果支持动态调整大小布局控件,则用户可以调整窗口大小。但我想添加一个垂直夹子(用红色表示),这样用户就可以使名称栏的宽度更大。
我对此做了一些研究,所有文章都已有近10年的历史,并没有考虑到新的动态调整大小控件。
仔细研究了这一点后,我发现“调整大小的抓手”一词不是我的意思。这是右下角的图标。我不是这个意思。
我相信你知道我的意思。可能吗?
添加自定义夹持器控件可能相对容易。请参阅下面的CMySplitter
课程。
但是如果所有控件都在一个对话框中,那么逐个重新定位/调整单个控件将非常困难。
理想情况下,使用两个子对话框。在资源编辑器中为各个控件设置调整大小/重新定位属性。将夹点控件置于两个对话框之间并调整大小以作响应。
夹持器控制等级:
#include <functional>
class CMySplitter : public CStatic
{
public:
class CPopup : public CWnd
{
public:
CMySplitter *parent;
int offset;
void OnMouseMove(UINT flag, CPoint pt);
void OnLButtonUp(UINT flag, CPoint pt);
DECLARE_MESSAGE_MAP()
};
std::function<void(int)> callback;
CRect boundary;
CPopup popup;
void OnLButtonDown(UINT flag, CPoint point);
void PreSubclassWindow();
void SetRange(int left, int right);
DECLARE_MESSAGE_MAP()
};
//create splitter control from a static control in dialog
void CMySplitter::PreSubclassWindow()
{
CStatic::PreSubclassWindow();
//modify static control's style (must have SS_NOTIFY)
SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_VISIBLE | SS_GRAYRECT | WS_CHILD | SS_NOTIFY);
//create a popup window with transparency
static CString classname =
AfxRegisterWndClass(0, 0, (HBRUSH)GetStockObject(BLACK_BRUSH));
popup.CreateEx(WS_EX_LAYERED | WS_EX_PALETTEWINDOW | WS_EX_NOACTIVATE,
classname, NULL, WS_POPUP, CRect(0, 0, 0, 0), this, 0);
popup.SetLayeredWindowAttributes(0, 128, LWA_ALPHA);
popup.parent = this;
}
//when user click the static control, show a popup window
void CMySplitter::OnLButtonDown(UINT flag, CPoint pt)
{
CStatic::OnLButtonDown(flag, pt);
GetCursorPos(&pt);
CRect rc;
GetWindowRect(&rc);
popup.offset = pt.x - rc.left;
popup.SetWindowPos(NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_SHOWWINDOW);
popup.SetCapture();
}
//how far to the left and right the splitter can go
void CMySplitter::SetRange(int left_, int right_)
{
CRect rc;
GetParent()->GetWindowRect(&rc);
boundary.left = rc.left + left_;
boundary.right = rc.right - right_;
}
//move this popup window
void CMySplitter::CPopup::OnMouseMove(UINT flag, CPoint pt)
{
CWnd::OnMouseMove(flag, pt);
GetCursorPos(&pt);
CRect rc;
GetWindowRect(&rc);
int x = pt.x - offset;
if (x > parent->boundary.left && x < parent->boundary.right)
SetWindowPos(NULL, x, rc.top, 0, 0, SWP_NOSIZE);
}
//hide popup window, let the parent dialog know
void CMySplitter::CPopup::OnLButtonUp(UINT flag, CPoint pt)
{
CWnd::OnLButtonUp(flag, pt);
ReleaseCapture();
ShowWindow(SW_HIDE);
CRect rc;
GetWindowRect(&rc);
parent->callback(rc.left);
}
BEGIN_MESSAGE_MAP(CMySplitter::CPopup, CWnd)
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
BEGIN_MESSAGE_MAP(CMySplitter, CWnd)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
用法:
使用IDC_STATIC1
向对话框添加静态控件,并按如下方式使用。
下面的代码有一个主要对话框CMyDialog
与IDD_DIALOG
,正常对话框
它有两个子对话框,child1和child2,IDD_PAGE1
和IDD_PAGE2
IDD_PAGE1
和IDD_PAGE2
是具有“子”风格的对话资源(不是弹出窗口)
class CMyDialog : public CDialogEx
{
public:
class CChild1 : public CDialogEx
{
};
class CChild2 : public CDialogEx
{
};
CChild1 child1;
CChild1 child2;
//respond to gripper resize
void respond(int position)
{
CRect rs;
m_splitter.GetWindowRect(&rs);
rs.MoveToX(position);
ScreenToClient(&rs);
CRect rc;
GetClientRect(&rc);
CRect r1(0, 0, rs.left, rc.bottom);
CRect r2(rs.right, 0, rc.right, rc.bottom);
child1.MoveWindow(r1, TRUE);
child2.MoveWindow(r2, TRUE);
m_splitter.MoveWindow(rs, TRUE);
m_splitter.Invalidate(TRUE);
}
CMySplitter m_splitter;
BOOL OnInitDialog()
{
CDialogEx::OnInitDialog();
child1.Create(IDD_PAGE1, this);
child2.Create(IDD_PAGE2, this);
m_splitter.SubclassDlgItem(IDC_STATIC1, this);
m_splitter.SetRange(50, 50);
m_splitter.callback = std::bind(&CMyDialog::respond, this, std::placeholders::_1);
//width for splitter
int dx = 10;
CRect rc;
GetClientRect(&rc);
CRect r1(0, 0, 200, rc.bottom);
CRect r2(r1.right + dx, 0, rc.right, rc.bottom);
CRect rs(r1.right, 10, r2.left, rc.bottom - 10);
child1.MoveWindow(r1);
child2.MoveWindow(r2);
m_splitter.MoveWindow(rs);
child1.ShowWindow(SW_SHOW);
child2.ShowWindow(SW_SHOW);
return TRUE;
}
...
};