在ObjectARX(VC)中使用MFC-可停靠窗体

目录

前言

一、使用CAD的CAcUiDockControlBar类

二、在入口程序中注册命令

三、窗口实现

四、目录结构

五、注意事项

六、效果展示


前言

CAD中经常会看到这样的窗口,下面就看看是如何实现的。


提示:以下是本篇文章正文内容,下面案例可供参考

一、使用CAD的CAcUiDockControlBar类

自己重写CAcUiDockControlBar类,实现creat方法,在里面弹出窗口。

 MyDockControlBar.h

#pragma once
#include "resource.h"

class CMyDockControlBar :public CAcUiDockControlBar
{
	DECLARE_DYNAMIC(CMyDockControlBar)

public:
	CMyDockControlBar();
	CString m_sTitle;
	virtual BOOL Create(CWnd* pParent, LPCSTR lpszTitle);
	void RedrawData();
	//其他内容
	BOOL      m_bMouseOver;
	COLORREF  m_clrNormal;
	COLORREF  m_clrHover;
	int m_cBorder;
	
protected:
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	virtual void SizeChanged(CRect* lpRect, BOOL bFloating, int flags);
	//其他功能函数
	afx_msg void OnPaint();
	virtual void PaintControlBar(CDC* pDC);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
	void OnClose();
	void RepositionBtn(); 
	CRect GetInsideRect();
	DECLARE_MESSAGE_MAP()
};

MyDockControlBar.cpp 

#include "stdafx.h"
#include "MyDockControlBar.h"
#include "DlgDockableForm.h"
static CLSID clsCModBar = { 0x7b771e1d, 0xf13e, 0x40d8, { 0xad, 0x0c, 0xd7, 0x45, 0xb3, 0xf8, 0x7b, 0xd7 } };

extern CDlgDockableForm* g_DlgDockableForm;

//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC(CMyDockControlBar, CAcUiDockControlBar)

BEGIN_MESSAGE_MAP(CMyDockControlBar, CAcUiDockControlBar)
	//{{AFX_MSG_MAP(CModBar)
	ON_WM_CREATE()
	//以下响应的是增强内容
	/*ON_WM_CLOSE()
	ON_WM_PAINT()
	ON_WM_MOUSEMOVE()
	ON_WM_ERASEBKGND()
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)*/

END_MESSAGE_MAP()
CMyDockControlBar::CMyDockControlBar() 
{
	m_cBorder = 4;                                //通用间距或边距
	m_bMouseOver = FALSE;                         //鼠标是否位于控件条主窗口区
	m_clrNormal = GetSysColor(COLOR_ACTIVECAPTION);//正常背景色
	m_clrHover = GetSysColor(COLOR_ACTIVECAPTION);      //鼠标在其上时的背景色
}

BOOL CMyDockControlBar::Create(CWnd* pParent, LPCSTR lpszTitle)
{
	CString strWndClass;
	int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
	int ScreenHeight = GetSystemMetrics(SM_CYSCREEN) ;
	strWndClass = AfxRegisterWndClass(CS_DBLCLKS, LoadCursor(NULL, IDC_ARROW));
	CRect rect(0, 0, ScreenWidth*0.3 , ScreenHeight*0.9);
	
	if (!CAcUiDockControlBar::Create(
		strWndClass,
		m_sTitle,
		WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN,
		rect,
		pParent, 0
	)
		)
		return (FALSE);

	SetToolID(&clsCModBar);


	return (TRUE);
}
int CMyDockControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CAcUiDockControlBar::OnCreate(lpCreateStruct) == -1)
		return (-1);
	//创建对话框
	g_DlgDockableForm = new CDlgDockableForm;
	BOOL bRtn = g_DlgDockableForm->Create(IDD_DIALOG_DOCKABLEFORM, this);
	g_DlgDockableForm->ShowWindow(SW_SHOW);
	ModifyStyle(0, WS_CLIPCHILDREN);
	return (0);
}
void CMyDockControlBar::RedrawData()
{
	if (g_DlgDockableForm)
	{
		g_DlgDockableForm->SetActiveWindow();
		g_DlgDockableForm->ShowWindow(SW_SHOW);
		if (g_DlgDockableForm->IsIconic() != 0)
		{
			g_DlgDockableForm->ShowWindow(SW_RESTORE);
		}

	}
	else
	{
		if ((g_DlgDockableForm = new CDlgDockableForm()) == NULL)
		{
			ads_printf(_T("Unable to allocate a CDlgItemMange."));
		}
		CAcModuleResourceOverride resOverride;

		BOOL succeeded = g_DlgDockableForm->Create(IDD_DIALOG_DOCKABLEFORM, this);
		if (!succeeded)
		{
			ads_printf(_T("\nUnable to create the dialog."));

		}
		g_DlgDockableForm->ShowWindow(SW_SHOW);
		g_DlgDockableForm->SetActiveWindow();
	}
}


//控件条尺寸或状态发生变化
void CMyDockControlBar::SizeChanged(CRect* lpRect, BOOL bFloating, int flags)
{
	CRect rc;
	//重定位关闭按钮
	RepositionBtn();
	//获取可直接使用的空间
	rc = GetInsideRect();

	if (g_DlgDockableForm->GetSafeHwnd() != NULL)
	{
		g_DlgDockableForm->MoveWindow(&rc);
	}
}


//以下是增强内容
//自定义绘制过程
void CMyDockControlBar::OnPaint()
{
	CPaintDC dc(this);
	PaintControlBar(&dc);
}
void CMyDockControlBar::PaintControlBar(CDC* pDC)
{
	CRect rect;
	//按照鼠标状态填充整个客户区
	GetClientRect(&rect);
	pDC->FillSolidRect(rect, m_bMouseOver ? m_clrHover : m_clrNormal);
	CFont font;
	font.CreateFont(
		15, // nHeight
		0, // nWidth
		0, // nEscapement
		0, // nOrientation
		FW_LIGHT, // nWeight
		FALSE, // bItalic
		FALSE, // bUnderline
		0, // cStrikeOut
		GB2312_CHARSET, // nCharSet
		OUT_DEFAULT_PRECIS, // nOutPrecision
		CLIP_DEFAULT_PRECIS, // nClipPrecision
		DEFAULT_QUALITY, // nQuality
		DEFAULT_PITCH | FF_SWISS,
		_T("Terminal") // nPitchAndFamily Arial
	);
	pDC->SelectObject(&font);
	//外边界向内收缩一个边宽度
	rect.DeflateRect(m_cBorder, m_cBorder);
	rect.left += 5;
	if (m_dwStyle & CBRS_ORIENT_HORZ)//水平停靠,把手画在右侧
	{
		pDC->DrawText(m_sTitle, rect, DT_LEFT);
	}
	else//垂直停靠,把手画在顶部
	{
		pDC->DrawText(m_sTitle, rect, DT_LEFT);
	}

}

//重新定位关闭按钮的位置
void CMyDockControlBar::RepositionBtn()
{
	CWnd* pBtn;
	CRect rect;
	if (IsFloating())
		return;

	pBtn = GetDlgItem(idCloseBtn);
	if (pBtn == NULL)
		return;

	GetClientRect(&rect);
	rect.DeflateRect(m_cBorder, m_cBorder);
	rect.left = rect.right - btnWidth;
	if (m_dwStyle & CBRS_ORIENT_HORZ)//水平停靠,按钮移至右下角
		rect.top = rect.bottom - btnHeight;
	else//垂直停靠,按钮移至右上角
		rect.bottom = rect.top + btnHeight;
	pBtn->MoveWindow(&rect);
	pBtn->ShowWindow(SW_SHOW);

	//框架浮动再停靠后,会多显示一个按钮,因为是CAD的无法删除,故而隐藏
	CWnd* pBtnPin = GetDlgItem(idPinBtn);
	if (pBtnPin != NULL)
	{
		pBtnPin->ShowWindow(SW_HIDE);
	}
}
//计算控件条内部可直接使用的空间
CRect CMyDockControlBar::GetInsideRect()
{
	CRect rect;
	GetClientRect(&rect);
	rect.DeflateRect(m_cBorder, m_cBorder);

	if (IsFloating())
		return rect;

	if (m_dwStyle & CBRS_ORIENT_HORZ)//水平停靠
		rect.DeflateRect(0, 0, m_cBorder + btnWidth, 0);
	else//垂直停靠
		rect.DeflateRect(0, m_cBorder + btnHeight, 0, 0);
	return rect;
}
void CMyDockControlBar::OnMouseMove(UINT nFlags, CPoint point)
{
	if (!m_bMouseOver)
	{
		//鼠标进入了控件条的主窗体
		m_bMouseOver = TRUE;
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.dwFlags = TME_LEAVE;
		tme.hwndTrack = m_hWnd;
		_TrackMouseEvent(&tme);
		Invalidate(FALSE);
	}
	CAcUiDockControlBar::OnMouseMove(nFlags, point);
}
BOOL CMyDockControlBar::OnEraseBkgnd(CDC* pDC)
{
	//防止重绘时的屏幕闪烁
	return TRUE;
}
void CMyDockControlBar::OnSize(UINT nType, int cx, int cy)
{
	if (g_DlgDockableForm->GetSafeHwnd() == NULL)
		return;
	CRect rc;
	rc = GetInsideRect();
	if (::IsWindow(g_DlgDockableForm->GetSafeHwnd())) {
		//- Forward the call
		CRect rect;
		GetWindowRect(&rect);
		//- Move the window over so we can see the control lines
		g_DlgDockableForm->MoveWindow(0, 0, rect.Width(), rect.Height(), TRUE);
	}
}
LRESULT CMyDockControlBar::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
	//鼠标离开了控件条主窗体
	if (m_bMouseOver)
	{
		m_bMouseOver = FALSE;
		Invalidate(FALSE);
	}
	return 0;
}
void CMyDockControlBar::OnClose()
{

	CAcUiDockControlBar::OnClose();
}

二、在入口程序中注册命令

 acrxEntryPoint.cpp


//-----------------------------------------------------------------------------
//----- acrxEntryPoint.cpp
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "resource.h"
#include "DlgDockableForm.h"
#include "MyDockControlBar.h"

//-----------------------------------------------------------------------------
#define szRDS _RXST("ADSK")
CMyDockControlBar* g_pgModBar;
extern CDlgDockableForm* g_DlgDockableForm;
void EndDockableFormDlg()
{
	if (g_DlgDockableForm)
	{
		g_DlgDockableForm->DestroyWindow();
		delete(g_DlgDockableForm);
		g_DlgDockableForm = NULL;
	}



	if (g_pgModBar)
	{
		g_pgModBar->DestroyWindow();
		delete g_pgModBar;
		g_pgModBar = NULL;
	}
}

//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
class CDockableDlgInCADApp : public AcRxArxApp {

public:
	CDockableDlgInCADApp () : AcRxArxApp () {}

	virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
		// TODO: Load dependencies here

		// You *must* call On_kInitAppMsg here
		AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
		
		// TODO: Add your initialization code here

		return (retCode) ;
	}

	virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
		// TODO: Add your code here

		// You *must* call On_kUnloadAppMsg here
		AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;

		EndDockableFormDlg();

		return (retCode) ;
	}

	virtual void RegisterServerComponents () {
	}
	

	static void ADSKMyGroupMyCommand () {
		// Put your command code here

	}

	// Modal Command with pickfirst selection
	// ACED_ARXCOMMAND_ENTRY_AUTO(CDockableDlgInCADApp, ADSKMyGroup, MyPickFirst, MyPickFirstLocal, ACRX_CMD_MODAL | ACRX_CMD_USEPICKSET)
	static void ADSKMyGroupMyPickFirst () {
		ads_name result ;
		int iRet =acedSSGet (ACRX_T("_I"), NULL, NULL, NULL, result) ;
		if ( iRet == RTNORM )
		{
			// There are selected entities
			// Put your command using pickfirst set code here
		}
		else
		{
			// There are no selected entities
			// Put your command code here
		}
	}

	// Application Session Command with localized name
	// ACED_ARXCOMMAND_ENTRY_AUTO(CDockableDlgInCADApp, ADSKMyGroup, MySessionCmd, MySessionCmdLocal, ACRX_CMD_MODAL | ACRX_CMD_SESSION)
	static void ADSKMyGroupMySessionCmd () {
		// Put your command code here
	}
	static void ADSKMyGroupShowDockableDlg() 
	{
		CAcModuleResourceOverride override;
		CMDIFrameWnd* pAcadFrame = acedGetAcadFrame();
		CString strTitle = _T("停靠窗口");
		if (g_pgModBar == NULL)
		{
			g_pgModBar = new CMyDockControlBar;
			g_pgModBar->m_sTitle = strTitle;
			USES_CONVERSION;
			g_pgModBar->Create(pAcadFrame, W2A(strTitle));
			g_pgModBar->EnableDocking(CBRS_ALIGN_LEFT | CBRS_ALIGN_RIGHT);
			pAcadFrame->DockControlBar(g_pgModBar, AFX_IDW_DOCKBAR_LEFT);
			g_pgModBar->ShowWindow(SW_HIDE);
		}
		else
		{
			g_pgModBar->RedrawData();
		}

		acedGetAcadFrame()->SetActiveWindow();
		acedGetAcadFrame()->SetFocus();

		pAcadFrame->ShowControlBar(g_pgModBar, TRUE, FALSE);
		pAcadFrame->RecalcLayout();
		g_pgModBar->ShowWindow(SW_SHOW);
	}

	
	static int ads_MyLispFunction () {
		//struct resbuf *args =acedGetArgs () ;
		
		// Put your command code here

		//acutRelRb (args) ;
		
		// Return a value to the AutoCAD Lisp Interpreter
		// acedRetNil, acedRetT, acedRetVoid, acedRetInt, acedRetReal, acedRetStr, acedRetPoint, acedRetName, acedRetList, acedRetVal

		return (RTNORM) ;
	}
	
} ;

//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CDockableDlgInCADApp)

ACED_ARXCOMMAND_ENTRY_AUTO(CDockableDlgInCADApp, ADSKMyGroup, MyCommand, MyCommandLocal, ACRX_CMD_MODAL, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CDockableDlgInCADApp, ADSKMyGroup, MyPickFirst, MyPickFirstLocal, ACRX_CMD_MODAL | ACRX_CMD_USEPICKSET, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CDockableDlgInCADApp, ADSKMyGroup, MySessionCmd, MySessionCmdLocal, ACRX_CMD_MODAL | ACRX_CMD_SESSION, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CDockableDlgInCADApp, ADSKMyGroup, ShowDockableDlg, ShowDockableDlg, ACRX_CMD_MODAL, NULL)
ACED_ADSSYMBOL_ENTRY_AUTO(CDockableDlgInCADApp, MyLispFunction, false)

 三、窗口实现

 DlgDockableForm.cpp: 实现文件

// DlgDockableForm.cpp: 实现文件
//

#include "stdafx.h"
#include "DlgDockableForm.h"
#include "afxdialogex.h"

CDlgDockableForm* g_DlgDockableForm;
// CDlgDockableForm 对话框

IMPLEMENT_DYNAMIC(CDlgDockableForm, CDialog)

CDlgDockableForm::CDlgDockableForm(CWnd* pParent /*=nullptr*/)
	: CDialog(IDD_DIALOG_DOCKABLEFORM, pParent)
{

}

CDlgDockableForm::~CDlgDockableForm()
{
}

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


BEGIN_MESSAGE_MAP(CDlgDockableForm, CDialog)
	ON_BN_CLICKED(IDC_BUTTON_CREATLINE, &CDlgDockableForm::OnBnClickedButtonCreatline)
	ON_WM_CLOSE()
END_MESSAGE_MAP()


// CDlgDockableForm 消息处理程序

LRESULT CDlgDockableForm::OnAcadKeepFocus(WPARAM, LPARAM)
{
	return TRUE;
}

void CDlgDockableForm::OnBnClickedButtonCreatline()
{
	ads_point ptStart;
	ads_point ptEnd;
	AcApDocument* pDoc = acDocManager->mdiActiveDocument();
	acDocManager->lockDocument(pDoc);

	AcDbBlockTable* pBlockTable;//声明指向块表的指针
	if (acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead) == Acad::eOk)
	{
		AcDbBlockTableRecord* pBlockTableRecord;//声明一个块表记录区的指针
		if (pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite) == Acad::eOk)
			//将空间模型区域的记录地址赋给上声明的变量 模式为写
		{
			if ((ads_getpoint(NULL, _T("\n请选择起点:"), ptStart)) == RTNORM)
			{
				if (ads_getpoint(NULL, _T("\n请选择终点:"), ptEnd) == RTNORM)
				{
					AcDbLine* pLine = new AcDbLine(asPnt3d(ptStart), asPnt3d(ptEnd));//这个类代表了CAD里面的线实体,起始点终结点
					AcDbObjectId lineld;//声明ID
					pBlockTableRecord->appendAcDbEntity(lineld, pLine);//将ID与实体传入
				//关闭所有这个很关键 用到了什么就要吧所有的都关闭不然会出现问题。
					pLine->close();
					pBlockTableRecord->close();
				}

			}


		}
		pBlockTable->close();
	}//获取块表织针
	acDocManager->unlockDocument(pDoc);//解锁

}



void CDlgDockableForm::OnClose()
{
	if (g_DlgDockableForm)
	{
		g_DlgDockableForm->DestroyWindow();
		delete(g_DlgDockableForm);
		g_DlgDockableForm = NULL;
	}

	CDialog::OnClose();
}


 DlgDockableForm.h

#pragma once

#include"resource.h"
// CDlgDockableForm 对话框

class CDlgDockableForm : public CDialog
{
	DECLARE_DYNAMIC(CDlgDockableForm)

public:
	CDlgDockableForm(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~CDlgDockableForm();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_DIALOG_DOCKABLEFORM };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
	afx_msg LRESULT OnAcadKeepFocus(WPARAM, LPARAM);
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedButtonCreatline();
	afx_msg void OnClose();

};

 四、目录结构

五、注意事项

对话框的边框和样式一定要设置对,

六、效果展示

参考

 在ObjectARX中使用MFC-可停靠窗体_GeekBuilding的博客-CSDN博客

源码地址:

我的sun&shine / DockableDlgInCAD · GitCode

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在 MFC(Microsoft Foundation Classes)使用 ObjectARX 绘制图形,您可以按照以下步骤进行操作: 1. 创建 MFC 应用程序:首先,您需要创建一个 MFC 应用程序项目。在 Visual Studio 选择“创建新项目”,然后选择“MFC 应用程序”。 2. 链接 ObjectARX:在项目设置,将 ObjectARX 库添加到项目的附加依赖项。这样可以确保您可以使用 ObjectARX API。 3. 初始化 ObjectARX:在 MFC 应用程序的初始化代码,调用 ObjectARX 的初始化函数,以确保 ObjectARX 的环境正确设置。 4. 绘制图形:在 MFC 应用程序的视图类,重写 OnDraw 函数,并使用 ObjectARX 提供的绘图函数来绘制图形。您可以使用 ObjectARX 的图形对象和绘图命令来创建和操作图形元素。 5. 处理用户输入:在 MFC 应用程序的视图类,重写相应的消息处理函数(例如 OnLButtonDown、OnMouseMove 等),以响应用户的鼠标或键盘输入。根据用户的输入,您可以调用 ObjectARX 提供的绘图函数来更新图形。 请注意,ObjectARX 是用于与 AutoCAD 进行集成开发的框架,它提供了一套 API 来创建和操作 AutoCAD 的图形对象。因此,在使用 MFC 绘制图形时,您需要了解 ObjectARX 的相关 API 和概念。 这只是一个简单的概述,具体的实现步骤可能会因您的需求和环境而有所不同。建议您参考 ObjectARX 和 MFC 的文档,并根据您的具体需求进行详细的开发和调试。希望这些信息对您有所帮助!如果您有更多具体的问题,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值