编写可托拽改变大小的对话框

 
编写可托拽改变大小的对话框
声明:本文不得转载,如需程序代码可给我发信索取。
 
我个人认为由于对话框改变大小后需要该对话框包含的所有子窗口进行重新排列,所有在MFC类中没有一个可托拽的对话框类。我编写了一个可托拽的对话框基类 CDragDialog,如果需要编写可托拽的对话框,可以继承该基类。
1.        位图资源的添加
将“标识鼠标拖拽有效区的位图”作为位图添加到资源,其ID为:“ IDB_BITMAP_DRAGBLOCK
2.        CDragDialog 类的定义
class CDragDialog : public CDialog
{
    DECLARE_DYNAMIC(CDragDialog)
 
public :
    CDragDialog(UINT nIDTemplate, CWnd* pParent = NULL);   // standard constructor
    virtual ~CDragDialog();
 
protected :
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 
    DECLARE_MESSAGE_MAP()
public :
    virtual BOOL OnInitDialog();
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    void SetMinSize(const CSize &size) { m_szMinSize = size; }
    bool GetTitleRect(CRect &rect) const;
    afx_msg void OnPaint();
    virtual void ReSizeContrals(void) { }
    afx_msg void OnSize(UINT nType, int cx, int cy);
protected :
    void ReSetDragBlock();
    void ReSizeDialog(const CPoint &point);
    void PaintDragBlock(CPaintDC &dc);
    CBitmap m_btDragBlock;
    CRect m_rcDragBlock;
    HCURSOR m_hcurDrag;
    HCURSOR m_hcurArrow;
    bool m_bDrag;
    CPoint m_ptLast;
    CSize m_szMinSize;
};
3.        CDragDialog 的成员函数的定义
IMPLEMENT_DYNAMIC (CDragDialog, CDialog)
CDragDialog ::CDragDialog(UINT nIDTemplate, CWnd* pParent /*=NULL*/)
: CDialog(nIDTemplate, pParent), m_rcDragBlock(0,0,0,0), m_szMinSize(100,40)
, m_bDrag(false), m_ptLast(0,0)
{
    m_btDragBlock.LoadBitmap(IDB_BITMAP_DRAGBLOCK);
    CWinApp*   pApp   =   ::AfxGetApp();
    m_hcurArrow = pApp->LoadStandardCursor(IDC_ARROW);
    m_hcurDrag = pApp->LoadStandardCursor(IDC_SIZENWSE);
}
 
CDragDialog ::~CDragDialog()
{
}
 
void CDragDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
}
 
 
BEGIN_MESSAGE_MAP (CDragDialog, CDialog)
    ON_WM_MOUSEMOVE()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_PAINT()
    ON_WM_SIZE()
END_MESSAGE_MAP ()
 
 
// CDragDialog message handlers
 
BOOL CDragDialog::OnInitDialog()
{
    CDialog::OnInitDialog();
 
    // TODO: Add extra initialization here
    CRect rect;
    GetClientRect(&rect);       //»ٌµأ؟ح»§اّ´َذ،
    BITMAP bitmap;
    m_btDragBlock.GetBitmap(&bitmap);
    m_rcDragBlock.left = rect.right - bitmap.bmWidth;
    m_rcDragBlock.top = rect.bottom - bitmap.bmHeight;
    m_rcDragBlock.right = rect.right;
    m_rcDragBlock.bottom = rect.bottom;
 
    ReSizeContrals();
 
    return TRUE// return TRUE unless you set the focus to a control
    // EXCEPTION: OCX Property Pages should return FALSE
}
 
void CDragDialog::ReSetDragBlock()
{
    CRect rect(0,0,0,0);
    GetClientRect(&rect);
    BITMAP bitmap;
    m_btDragBlock.GetBitmap(&bitmap);
    m_rcDragBlock.left = rect.right - bitmap.bmWidth;
    m_rcDragBlock.top = rect.bottom - bitmap.bmHeight;
    m_rcDragBlock.right = rect.right;
    m_rcDragBlock.bottom = rect.bottom;
}
 
void CDragDialog::PaintDragBlock(CPaintDC &dc)
{
    CDC dcMemory;
    dcMemory.CreateCompatibleDC(&dc);
    CBitmap* pOldBitmap = dcMemory.SelectObject(&m_btDragBlock);
 
    dc.BitBlt(m_rcDragBlock.left, m_rcDragBlock.top, m_rcDragBlock.Width(),m_rcDragBlock.Height(),
        &dcMemory,0, 0, SRCCOPY);
 
    dcMemory.SelectObject(pOldBitmap);
}
 
bool CDragDialog::GetTitleRect(CRect &rect) const
{
    if (!::IsWindow(this->m_hWnd))
    {
        return false;
    }
 
    CRect rcWindow(0,0,0,0);
    GetWindowRect(&rcWindow);
    CRect rcClient(0,0,0,0);
    GetClientRect(rcClient);
    rect = rcWindow;
    rect.bottom = rcWindow.bottom - rcClient.Height();
    return true;
}
 
void CDragDialog::ReSizeDialog(const CPoint &point)
{
    if (!m_bDrag)
        return;
 
    CRect rcWindow(0,0,0,0);
    GetWindowRect(&rcWindow);
    CRect rcTitle(0,0,0,0);
    GetTitleRect(rcTitle);
    int nTitleHeight = rcTitle.Height();
    if (point.x < m_szMinSize.cx && point.y < m_szMinSize.cy - nTitleHeight)
    {
        SetWindowPos(&CWnd::wndTopMost, 0, 0, m_szMinSize.cx, m_szMinSize.cy, SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
    }
    else if (point.x < m_szMinSize.cx)
    {
        SetWindowPos(&CWnd::wndTopMost, 0, 0, m_szMinSize.cx, rcWindow.Height() + (point.y - m_ptLast.y), SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
    }
    else if (point.y < m_szMinSize.cy - nTitleHeight)
    {
        SetWindowPos(&CWnd::wndTopMost, 0, 0, rcWindow.Width() + (point.x - m_ptLast.x), m_szMinSize.cy, SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
    }
    else
    {
        SetWindowPos(&CWnd::wndTopMost, 0, 0, rcWindow.Width() + (point.x - m_ptLast.x), rcWindow.Height() + (point.y - m_ptLast.y), SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
    }
    if (NULL != GetParent())
    {
        //GetParent()->InvalidateRect(rcWindow);
        GetParent()->Invalidate();
    }
}
 
void CDragDialog::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    if (m_bDrag)
    {
        ::SetCursor(m_hcurDrag);
        ReSizeDialog(point);
        m_ptLast = point;
        Invalidate();
        ReSetDragBlock();
    }
    else if (m_rcDragBlock.PtInRect(point))
    {
        ::SetCursor(m_hcurDrag);
    }
    else
    {
        ::SetCursor(m_hcurArrow);
    }
 
    CDialog::OnMouseMove(nFlags, point);
}
 
void CDragDialog::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    if (m_rcDragBlock.PtInRect(point))
    {
        m_bDrag = true;
        ::SetCursor(m_hcurDrag);
        SetCapture();
        m_ptLast = point;
    }
 
    CDialog::OnLButtonDown(nFlags, point);
}
 
void CDragDialog::OnLButtonUp(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    if (m_bDrag)
    {
        m_bDrag = false;
        ::SetCursor(m_hcurArrow);
        ReleaseCapture();
        m_ptLast = CPoint(0,0);
    }
 
    CDialog::OnLButtonUp(nFlags, point);
}
 
 
void CDragDialog::OnSize(UINT nType, int cx, int cy)
{
    CDialog::OnSize(nType, cx, cy);
 
    // TODO: Add your message handler code here
    ReSizeContrals();
}
 
4.        派生类所做的工作
派生类需要做的工作为:
1) 重定义基类的 ReSizeContrals虚函数,函数内容为重新排列对话框中的控件(可用 SetWindowPosMoveWindow函数)。
2) 在派生类的 OnPaint函数中调用 PaintDragBlock函数。 PaintDragBlock函数的作用是在对话框的右下角画出“标识鼠标拖拽有效区的位图”。
5.        我所写的派生类的定义
class CDrugDlgDlg : public CDragDialog
{
public :
    CDrugDlgDlg(CWnd* pParent = NULL); // ±ê×¼¹¹شى؛¯ت‎
 
    enum { IDD = IDD_DRUGDLG_DIALOG };
 
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV ض§³ض
 
 
protected :
    HICON m_hIcon;
 
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
private :
    CButton m_ctlOK;
    CButton m_ctlCancle;
public :
    virtual void ReSizeContrals(void);
};
6.        我所写的派生类的成员函数定义
我建立的工程是基于对话框的,如果工程是单文档或多问档派生类成员函数的定义会略有不同。
CDrugDlgDlg ::CDrugDlgDlg(CWnd* pParent /*=NULL*/)
    : CDragDialog(CDrugDlgDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
 
void CDrugDlgDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDOK, m_ctlOK);
    DDX_Control(pDX, IDCANCEL, m_ctlCancle);
}
 
BEGIN_MESSAGE_MAP (CDrugDlgDlg, CDragDialog)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP ()
 
 
BOOL CDrugDlgDlg::OnInitDialog()
{
    CDragDialog::OnInitDialog();
 
 
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);
 
    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        CString strAboutMenu;
        strAboutMenu.LoadString(IDS_ABOUTBOX);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }
 
    SetIcon(m_hIcon, TRUE);        
    SetIcon(m_hIcon, FALSE);       
 
    return TRUE
}
 
void CDrugDlgDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDragDialog::OnSysCommand(nID, lParam);
    }
}
 
void CDrugDlgDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this);
        PaintDragBlock(dc);
 
        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
 
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;
 
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDragDialog::OnPaint();
    }
}
 
HCURSOR CDrugDlgDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}
 
void CDragDialog::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    // TODO: Add your message handler code here
    // Do not call CDialog::OnPaint() for painting messages
    PaintDragBlock(dc);
}
 
void CDrugDlgDlg::ReSizeContrals(void)
{
    if (::IsWindow(this->m_hWnd))
    {
        CRect rect(0,0,0,0);
        GetClientRect(&rect);
        if (::IsWindow(m_ctlOK.m_hWnd) && ::IsWindow(m_ctlCancle.m_hWnd))
        {
            m_ctlOK.SetWindowPos(&CWnd::wndTop,15,15,rect.Width()-30,(int)(rect.Height()/2)-15,SWP_NOZORDER);
            m_ctlCancle.SetWindowPos(&CWnd::wndTop,15,(int)(rect.Height()/2),rect.Width()-30,(int)(rect.Height()/2)-15,SWP_NOZORDER);
        }
    }
}
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值