Duilib在MFC中使用

最近被安排UI工作有点多,公司的控件用不顺手,也有用DUILIB的,但是问了公司的几个人说和MFC一起用的时候有这样那样的问题。
今天手痒实验了下直接在CDLG里边用DUILIB(我不想直接用duilib了事,后期可能会做做大改动,所以没有直接在duilib::CWindowWnd里边想办法)
发现唯一需要注意的就是需要在OnPaint中屏蔽CDialog的paint,,,duilib还是很牛逼的
同样,把duilib整合成MFC的“插件”之后,那个CWindowWnd::Close会自动delete this的故障也没了,额,应该说是特性,不是故障,,,不过这个特性给我带来的麻烦比较多,,,
 
// dui_mfcDlg.h : header file
//

#pragma once

// Cdui_mfcDlg dialog
class Cdui_mfcDlg : public CDialog
    , public DuiLib::INotifyUI, public DuiLib::IMessageFilterUI
{
// Construction
public:
 Cdui_mfcDlg(CWnd* pParent = NULL);    // standard constructor

// Dialog Data
   enum { IDD = IDD_DUI_MFC_DIALOG };

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support


// Implementation
protected:
    HICON m_hIcon;

    // Generated message map functions
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()

private:
    bool OnHChanged(void* param) {
        DuiLib::TNotifyUI* pMsg = (DuiLib::TNotifyUI*)param;
        if( pMsg->sType == _T("valuechanged") ) {
            short H, S, L;
            DuiLib::CPaintManagerUI::GetHSL(&H, &S, &L);
            DuiLib::CPaintManagerUI::SetHSL(true, (static_cast<DuiLib::CSliderUI*>(pMsg->pSender))->GetValue(), S, L);
        }
        return true;
    }

    bool OnSChanged(void* param) {
        DuiLib::TNotifyUI* pMsg = (DuiLib::TNotifyUI*)param;
        if( pMsg->sType == _T("valuechanged") ) {
            short H, S, L;
            DuiLib::CPaintManagerUI::GetHSL(&H, &S, &L);
            DuiLib::CPaintManagerUI::SetHSL(true, H, (static_cast<DuiLib::CSliderUI*>(pMsg->pSender))->GetValue(), L);
        }
        return true;
    }

    bool OnLChanged(void* param) {
        DuiLib::TNotifyUI* pMsg = (DuiLib::TNotifyUI*)param;
        if( pMsg->sType == _T("valuechanged") ) {
            short H, S, L;
            DuiLib::CPaintManagerUI::GetHSL(&H, &S, &L);
            DuiLib::CPaintManagerUI::SetHSL(true, H, S, (static_cast<DuiLib::CSliderUI*>(pMsg->pSender))->GetValue());
        }
        return true;
    }

    bool OnAlphaChanged(void* param) {
        DuiLib::TNotifyUI* pMsg = (DuiLib::TNotifyUI*)param;
        if( pMsg->sType == _T("valuechanged") ) {
            m_pm.SetTransparent((static_cast<DuiLib::CSliderUI*>(pMsg->pSender))->GetValue());
        }
        return true;
    }

    void OnPrepare() 
    {
        DuiLib::CSliderUI* pSilder = static_cast<DuiLib::CSliderUI*>(m_pm.FindControl(_T("alpha_controlor")));
        if( pSilder ) pSilder->OnNotify += MakeDelegate(this, &Cdui_mfcDlg::OnAlphaChanged);
        pSilder = static_cast<DuiLib::CSliderUI*>(m_pm.FindControl(_T("h_controlor")));
        if( pSilder ) pSilder->OnNotify += MakeDelegate(this, &Cdui_mfcDlg::OnHChanged);
        pSilder = static_cast<DuiLib::CSliderUI*>(m_pm.FindControl(_T("s_controlor")));
        if( pSilder ) pSilder->OnNotify += MakeDelegate(this, &Cdui_mfcDlg::OnSChanged);
        pSilder = static_cast<DuiLib::CSliderUI*>(m_pm.FindControl(_T("l_controlor")));
        if( pSilder ) pSilder->OnNotify += MakeDelegate(this, &Cdui_mfcDlg::OnLChanged);
    }

private:
    DuiLib::CPaintManagerUI m_pm;

    // INotifyUI
public:
    virtual void Notify(DuiLib::TNotifyUI& msg);

    // IMessageFilterUI 
public:
    virtual LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled);
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
};
 

 

// dui_mfcDlg.cpp : implementation file
//

#include "stdafx.h"
#include "dui_mfc.h"
#include "dui_mfcDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
 CAboutDlg();

// Dialog Data
 enum { IDD = IDD_ABOUTBOX };

 protected:
 virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
 DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// Cdui_mfcDlg dialog

 


Cdui_mfcDlg::Cdui_mfcDlg(CWnd* pParent /*=NULL*/)
 : CDialog(Cdui_mfcDlg::IDD, pParent)
{
 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void Cdui_mfcDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(Cdui_mfcDlg, CDialog)
 ON_WM_SYSCOMMAND()
 ON_WM_PAINT()
 ON_WM_QUERYDRAGICON()
 //}}AFX_MSG_MAP
    ON_WM_CREATE()
END_MESSAGE_MAP()


// Cdui_mfcDlg message handlers

BOOL Cdui_mfcDlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // Add "About..." menu item to system menu.

 // IDM_ABOUTBOX must be in the system command range.
 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 ASSERT(IDM_ABOUTBOX < 0xF000);

 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
  BOOL bNameValid;
  CString strAboutMenu;
  bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
  ASSERT(bNameValid);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
 }

 // Set the icon for this dialog.  The framework does this automatically
 //  when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE);   // Set big icon
 SetIcon(m_hIcon, FALSE);  // Set small icon

 // TODO: Add extra initialization here

 return TRUE;  // return TRUE  unless you set the focus to a control
}

void Cdui_mfcDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
 {
  CAboutDlg dlgAbout;
  dlgAbout.DoModal();
 }
 else
 {
  CDialog::OnSysCommand(nID, lParam);
 }
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void Cdui_mfcDlg::OnPaint()
{
 if (IsIconic())
 {
  CPaintDC dc(this); // device context for painting

  SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

  // Center icon in client rectangle
  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;

  // Draw the icon
  dc.DrawIcon(x, y, m_hIcon);
 }
 else
 {
  //CDialog::OnPaint();
 }
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR Cdui_mfcDlg::OnQueryDragIcon()
{
 return static_cast<HCURSOR>(m_hIcon);
}


void Cdui_mfcDlg::Notify(DuiLib::TNotifyUI& msg)
{
    if( msg.sType == _T("windowinit") ) OnPrepare();
    else if( msg.sType == _T("click") ) {
        if( msg.pSender->GetName() == _T("insertimagebtn") ) {
            DuiLib::CRichEditUI* pRich = static_cast<DuiLib::CRichEditUI*>(m_pm.FindControl(_T("testrichedit")));
            if( pRich ) {
                pRich->RemoveAll();
            }
        }
        else if( msg.pSender->GetName() == _T("changeskinbtn") ) {
            if( DuiLib::CPaintManagerUI::GetResourcePath() == DuiLib::CPaintManagerUI::GetInstancePath() )
                DuiLib::CPaintManagerUI::SetResourcePath(DuiLib::CPaintManagerUI::GetInstancePath() + _T("skin\\FlashRes"));
            else
                DuiLib::CPaintManagerUI::SetResourcePath(DuiLib::CPaintManagerUI::GetInstancePath());
            DuiLib::CPaintManagerUI::ReloadSkin();
        }
    }
}

LRESULT Cdui_mfcDlg::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
    if( uMsg == WM_ERASEBKGND ) 
    {
        return true;
    }

    return false;
}
BOOL Cdui_mfcDlg::PreTranslateMessage(MSG* pMsg)
{
    // TODO: Add your specialized code here and/or call the base class
    bool bHandled = false;
    MessageHandler(pMsg->message, pMsg->wParam, pMsg->lParam, bHandled);
    if (bHandled)
    {
        return true;
    }
    else
    {
        LRESULT lresult = 0;
        if (m_pm.MessageHandler(pMsg->message, pMsg->wParam, pMsg->lParam, lresult))
        {
            return lresult;
        }
    }

    return __super::PreTranslateMessage(pMsg);
}

int Cdui_mfcDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (__super::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  Add your specialized creation code here
    m_pm.Init(m_hWnd);
    DuiLib::CDialogBuilder builder;
    DuiLib::CControlUI* pRoot = builder.Create(_T("test1.xml"), (UINT)0, NULL, &m_pm);
    ASSERT(pRoot && "Failed to parse XML");
    m_pm.AttachDialog(pRoot);
    m_pm.AddNotifier(this);

    return 0;
}



注:在WindowProc 调用消息处理要比在PreTranslateMessage调用更合理。

duilib 是一个开源的界面库,它提供了丰富的界面控件和布局管理功能,非常适合用于开发Windows桌面软件。而MFC(Microsoft Foundation Class)是微软开发的用于Windows平台的C++类库,提供了大量的封装好的功能和控件,方便开发人员进行Windows应用程序的开发。 在duilib使用MFC的PictureControl控件,需要先在项目引入MFC库,并创建一个MFC应用程序。然后,在duilib的界面布局文件使用窗口控件,并设置控件类型为"Pic",通过name属性给控件命名。 接下来,在MFC应用程序,创建一个继承自duilib::CPaintManagerUI的类,重写其的虚函数Notify,用于监听控件的消息事件。在Notify函数,通过duilib的API获取到PictureControl控件的指针,并调用MFC的相关函数,实现图片的加载和显示。 具体代码如下所示: 在duilib界面布局文件(XML)添加如下代码: ```xml <Control name="picControl" type="Pic" pos="10, 10, 100, 100" /> ``` 在MFC应用程序的窗口类添加如下代码: ```cpp class CMainWnd : public CDialogEx { public: CMainWnd(CWnd* pParent = nullptr) : CDialogEx(IDD_MAIN_DIALOG, pParent) { } protected: virtual void DoDataExchange(CDataExchange* pDX) override { CDialogEx::DoDataExchange(pDX); } afx_msg void OnPaint() { CPaintDC dc(this); // 获取duilib的PictureControl控件指针 duilib::CPictureUI* pPicControl = (duilib::CPictureUI*)GetDlgItem(IDC_DUI_PIC); if (pPicControl == nullptr) return; // 获取MFC的CDC对象 CDC* pDC = CDC::FromHandle(dc.GetSafeHdc()); // 加载图片 CImage image; image.Load(_T("path_to_your_image")); // 绘制图片 image.Draw(pDC->GetSafeHdc(), pPicControl->GetPos().left, pPicControl->GetPos().top, pPicControl->GetPos().Width(), pPicControl->GetPos().Height()); } DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CMainWnd, CDialogEx) ON_WM_PAINT() END_MESSAGE_MAP() ``` 以上就是在duilib使用MFC的PictureControl控件的步骤,通过上述代码,可以实现在duilib界面显示MFC加载的图片。当然,在实际的项目,可能还需要添加图片缩放、鼠标事件等处理逻辑,具体根据实际需求进行扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值