# UIDesigner **Repository Path**: nkjpj/UIDesigner ## Basic Information - **Project Name**: UIDesigner - **Description**: 踏雪流云写的UIDesigner,非常好的MFC多文档学习资料 - **Primary Language**: Unknown - **License**: BSD-2-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 4 - **Created**: 2019-11-04 - **Last Updated**: 2024-11-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README UIDesigner的原理 1、HOOKAPI ```c CHookAPI::CHookAPI(void) { #ifdef _DEBUG CreateFileAPI=(pfnCreateFile)HookAPI(_T("KERNEL32.dll"),LPCSTR("CreateFileW"),(FARPROC)Hook_CreateFile,GetModuleHandle(_T("Duilib_ud.dll"))); EnableCreateFile(true); HookAPI(_T("Duilib_ud.dll"),LPCSTR("?Invalidate@CPaintManagerUI@DuiLib@@QAEXAAUtagRECT@@@Z"),(FARPROC)Hook_Invalidate,m_InvalidateHookInfo); EnableInvalidate(true); HookAPI(_T("Duilib_ud.dll"),LPCSTR("?GetImageEx@CPaintManagerUI@DuiLib@@QAEPAUtagTImageInfo@2@PB_W0K@Z"),(FARPROC)Hook_GetImageEx,m_GetImageExHookInfo); EnableGetImageEx(true); #else CreateFileAPI=(pfnCreateFile)HookAPI(_T("KERNEL32.dll"),LPCSTR("CreateFileW"),(FARPROC)Hook_CreateFile,GetModuleHandle(_T("Duilib_u.dll"))); EnableCreateFile(true); HookAPI(_T("Duilib_u.dll"),LPCSTR("?Invalidate@CPaintManagerUI@DuiLib@@QAEXAAUtagRECT@@@Z"),(FARPROC)Hook_Invalidate,m_InvalidateHookInfo); EnableInvalidate(true); HookAPI(_T("Duilib_u.dll"),LPCSTR("?GetImageEx@CPaintManagerUI@DuiLib@@QAEPAUtagTImageInfo@2@PB_W0K@Z"),(FARPROC)Hook_GetImageEx,m_GetImageExHookInfo); EnableGetImageEx(true); #endif } ``` Hook_Invalidate的目的是为了绘制界面效果,增加控件的矩形大小,用来绘制绿色边框和虚线边框。 ![Control_show.png](Control_show.png) 2、中间的画板区域 CLayoutManager m_LayoutManager; CLayoutManager 继承自duilib的IDialogBuilderCallback类。 ```c class CLayoutManager : public IDialogBuilderCallback CLayoutManager m_LayoutManager; ``` ```c // CUIDesignerView 绘制 void CUIDesignerView::OnDraw(CDC* pDrawDC) { CUIDesignerDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: 在此处为本机数据添加绘制代码 CMemDC memDC(*pDrawDC, this); CDC* pDC = &memDC.GetDC(); CRect rectClient; GetClientRect(rectClient); CPoint point=GetScrollPosition(); rectClient.OffsetRect(point); pDC->FillSolidRect(rectClient,RGB(255, 255, 255)); // 获取duilib界面的大小 CSize szForm=m_LayoutManager.GetForm()->GetInitSize(); CSize szFormOffset(FORM_OFFSET_X,FORM_OFFSET_Y); CDC hCloneDC; HBITMAP hNewBitmap; hCloneDC.CreateCompatibleDC(pDC); // 创建一张位图 hNewBitmap=::CreateCompatibleBitmap(pDC->GetSafeHdc(),szForm.cx,szForm.cy); HBITMAP hOldBitmap=(HBITMAP)hCloneDC.SelectObject(hNewBitmap); // 这里绘制 m_LayoutManager.Draw(&hCloneDC); pDC->BitBlt(szFormOffset.cx,szFormOffset.cy,szForm.cx,szForm.cy,&hCloneDC,0,0,SRCCOPY); hCloneDC.SelectObject(hOldBitmap); ::DeleteDC(hCloneDC); ::DeleteObject(hNewBitmap); m_MultiTracker.Draw(pDC,&szFormOffset); } ``` 3、控件跟踪器,负责选中控件的管理。内部有两个指针数组,分别保存选中的控件和控件的矩形大小。矩形数组主要是用于绘制。 CUIDesignerView::OnLButtonDown ---> m_MultiTracker 鼠标单击控件是执行的操作。 ```c void CUIDesignerView::OnLButtonDown(UINT nFlags, CPoint point) { // 。。。 // 通过鼠标的点击点获取控件 CControlUI* pControl=m_LayoutManager.FindControl(ptLogical); CTrackerElement* pTracker=NULL; if(pControl==NULL) pControl=m_LayoutManager.GetForm(); int nHit=m_MultiTracker.HitTest(ptLogical); int nType=GetControlType(pControl); if((nFlags&MK_CONTROL)==0&&nHit==hitNothing) m_MultiTracker.RemoveAll(); // 鼠标点有控件,new一个跟踪元素CTrackerElement。 // 跟踪元素绑定通过Add绑定到跟踪器,支持多选 if(nHit==hitNothing) m_MultiTracker.Add(CreateTracker(pControl)); else m_MultiTracker.SetFocus(ptLogical); if(nHit>=0||nType==typeControl) { // 注意这里面传入了dc,进行了绘制 // DrawTrackerRect m_MultiTracker.Track(this, ptLogical, FALSE,&dc); } else { ``` 4、修改控件属性,分三步执行。 (1)、PosBeginChanged通知m_UICommandHistory创建CUICommandElement* m_pBefore记录,内部保存一个TiXmlElement,用于保存此时的数据。 ```xml