目录
前言
一、使用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