UGNX二次开发——截图功能

        在NX中没有截图功能,为了方便加工工艺人员制定工艺是制作缩略图,本文介绍三种方法,也许会有第四种,参考【NX二次开发】视图对象截图。但是个人认为适合自己的才是最好。因为要制作一个案例,参考知网论文:一种自动输出数控程序清单的NX二次开发方法中用到该功能,因此提前进行实验功能是否可以使用。本人做过Creo二次开发,sw二次开法,NX二次开发,截至目前最感兴趣的是NX二次开发,作为新生真的有太多的无奈了,程序有太多的BUG了,能坚持到现在,其中要感谢各位博客博主,也要感谢王牌飞行员_里海,以及其他大佬,自学这个已经一年有余,每次遇到BUG是总会有人伸出援手,对此万分感谢。因此博主会分享给各位自己在学习中的一些问题以及解决方案。当然也有自己的小专题,有时需要一瓶饮料,内容可能不是那么完美,但是足够给新手提供思路。

第一种方法,使用单选函数进行截图。个人评价代码太多,哈哈哈,好像之高清截图。

//用户定义
#include <uf_ui.h>
#include <uf_part.h>
#include <uf_csys.h>
#include <uf_disp.h>
#include <uf_modl.h>
#include <uf_trns.h>
#include <uf_ui.h>
#include <uf_vec.h>
#include <uf_view.h>
#include <afx.h>


//用户定义
// 获取输入体相对于NX视图的左上角与右下角坐标
static void GetTwoPoints(tag_t body, double leftT[3], double rightB[3])
{
	// 创建临时坐标系
	UF_initialize();
	double temp = 0.0;
	double csys[12] = { 0.0 };
	tag_t mtxId = NULL_TAG, csysId = NULL_TAG;
	uc6430("", &csys[0], &temp);
	uc6433("", &csys[3]);
	UF_CSYS_create_matrix(&csys[3], &mtxId);
	UF_CSYS_create_temp_csys(&csys[0], mtxId, &csysId);

	// 计算包围盒并求得左上角与右下角的坐标
	double min[3] = { 0.0 };
	double dists[3] = { 0.0 };
	double dirs[3][3] = { { 0.0 },{ 0.0 },{ 0.0 } };
	UF_MODL_ask_bounding_box_aligned(body, csysId, 0, min, dirs, dists);
	UF_VEC3_affine_comb(min, dists[1], &dirs[1][0], leftT);
	UF_VEC3_affine_comb(min, dists[0], &dirs[0][0], rightB);

	// 将绝对坐标系的点转换为NX视图坐标
	int status = 0;
	double matrix[12] = { 0.0 };
	double abs[9] = { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0 };
	uf5940(abs, &csys[0], matrix, &status);
	uf5941(leftT, matrix);
	uf5941(rightB, matrix);
	UF_terminate();
}
// NX视图坐标转屏幕像素坐标
static bool GetScreenPt(double p1[3], double p2[3], POINT pts[2])
{
	UF_initialize();
	HWND nxHwnd = (HWND)UF_UI_get_default_parent();
	HWND drawZone = FindWindowEx(nxHwnd, NULL, L"NX_SURFACE_WND", NULL);
	drawZone = FindWindowEx(nxHwnd, drawZone, L"NX_SURFACE_WND", NULL);
	drawZone = GetWindow(drawZone, GW_CHILD);
	if (drawZone == NULL)
	{
		return false;
	}

	double clip[4] = { 0.0, 1.0, 0.0, 1.0 };
	tag_t workView = NULL_TAG;
	UF_VIEW_ask_work_view(&workView);
	UF_VIEW_ask_current_xy_clip(workView, clip);

	RECT draw = { 0 };
	GetWindowRect(drawZone, &draw); // 获取绘图区在屏幕的大小
	long length = draw.right - draw.left;
	long width = draw.bottom - draw.top;
	double xSizeView = clip[1] - clip[0];
	double ySizeView = clip[3] - clip[2];

	double x1 = draw.left + (p1[0] - clip[0]) / xSizeView * length;
	double x2 = draw.left + (p2[0] - clip[0]) / xSizeView * length;
	double y1 = draw.bottom - (p1[1] - clip[2]) / ySizeView * width;
	double y2 = draw.bottom - (p2[1] - clip[2]) / ySizeView * width;

	pts[0].x = (long)floor(x1);
	pts[0].y = (long)ceil(y1);
	pts[1].x = (long)ceil(x2);
	pts[1].y = (long)floor(y2);

	// 计算机屏幕坐标转换为Client
	ScreenToClient(drawZone, &pts[0]);
	ScreenToClient(drawZone, &pts[1]);
	UF_terminate();
	return true;
}


static int init_proc(
	UF_UI_selection_p_t select,
	void* user_data)
{
	int num_triples = 1;
	UF_UI_mask_t mask_triples = { UF_solid_type, 0, UF_UI_SEL_FEATURE_BODY };
	/* enable only lines and edges */
	if (UF_UI_set_sel_mask(select,
		UF_UI_SEL_MASK_CLEAR_AND_ENABLE_SPECIFIC,
		num_triples, &mask_triples) == 0)
	{
		return (UF_UI_SEL_SUCCESS);
	}
	else
	{
		return (UF_UI_SEL_FAILURE);
	}
}



void MyClass::do_it()
{

	// TODO: add your code here
	UF_initialize();
	// 0.使用NXOpen C用户界面
	/*char* msg = "Select Object";
	UF_UI_mask_t mask = { UF_solid_type, 0, UF_UI_SEL_FEATURE_BODY };

	UF_UI_selection_options_t opts = { 0 };
	opts.other_options = 0;
	opts.reserved = NULL;
	opts.num_mask_triples = 1;
	opts.mask_triples = &mask;
	opts.scope = UF_UI_SEL_SCOPE_WORK_PART;

	int response = 0;
	tag_t body = NULL_TAG, view = NULL_TAG;
	double cursor[3] = { 0.0 };
	UF_UI_select_single(msg, &opts, &response, &body, cursor, &view);*/
	char cue[] = "cue message";
	char title[] = "截图工具包围盒";
	int response;
	tag_t body, view;
	double cursor[3];
	UF_UI_select_with_single_dialog(cue, title,UF_UI_SEL_SCOPE_NO_CHANGE, init_proc, NULL,&response, &body, cursor, &view);
	char partname[MAX_FSPEC_BUFSIZE + 1];
	//查找部件名字
	UF_PART_ask_part_name(UF_PART_ask_display_part(), partname);

	string name = partname;
	int pos = name.find_last_of('\\');
	string s1(name.substr(pos + 1));
	//分割字符串(只读取part名)
	string s2(s1.substr(0, s1.find(".")));

	// 1.将选择的对象导出成图片
	if (body != NULL_TAG)
	{
		UF_DISP_set_highlight(body, 0);

		// 1.1获取输入体相对于NX视图的左上角与右下角坐标
		double leftTop[3] = { 0.0 }, rightBottom[3] = { 0.0 };
		GetTwoPoints(body, leftTop, rightBottom);

		// 1.2NX视图坐标转屏幕像素坐标
		POINT pts[2] = { { 0 },{ 0 } };
		bool status = GetScreenPt(leftTop, rightBottom, pts);

		// 1.3创建截图
		string panthqian = "D:\\nxopen_demo\\";
		string panthhou = ".png";
		string panth = panthqian+s2+ panthhou;

		char* filename = (char*)panth.c_str();

		if (status)
		{
			int corner[2] = { pts[0].x, pts[0].y };
			int width = pts[1].x - pts[0].x;
			int height = pts[1].y - pts[0].y;
			UF_DISP_create_framed_image(filename,UF_DISP_PNG, UF_DISP_WHITE, corner, width, height);
		}
	}
	UF_terminate();
	
}

第二种方法,巧妙用运函数PVT_create_preview,进行视图截取

//用户定义
#include <uf.h>
#include <UF_DISP.h>
#include <uf_view.h>
#include <uf_assem.h>
#include <uf_part.h>



	UF_initialize();  
    //创建预览对话框 
	//libugutilsint.dll
	//调内部函数PVT_create_preview创建预览对话框 
	typedef void(*load_ufusr_f_p_t)(unsigned int v1, char const * v2, int v3, unsigned int const * v4, int v5, unsigned int const * v6, bool v7, bool v8, class PVT_view_prefs_s * const v9, enum PVT_cancel_type v10, bool v11, int * v12);//定义传参 
	load_ufusr_f_p_t PVT_create_preview = NULL; 
	UF_load_library("D:\\ug\\NXBIN\\libugutilsint.dll", "?PVT_create_preview@@YAPEAUPVT_view_info_s@@IPEBDHPEBIH1_N2QEAUPVT_view_prefs_s@@W4PVT_cancel_type@@2PEAH@Z", (UF_load_f_p_t *)&PVT_create_preview); 
	//调内部函数PVT_init_view_preferences初始化预览参数 
	typedef void(*load_ufusr_f_p_t1)(class PVT_view_prefs_s * v1);//定义传参 
	load_ufusr_f_p_t1 PVT_init_view_preferences = NULL; 
	UF_load_library("D:\\ug\\NXBIN\\libugutilsint.dll", "?PVT_init_view_preferences@@YAXPEAUPVT_view_prefs_s@@@Z", (UF_load_f_p_t *)&PVT_init_view_preferences);  
	if (PVT_create_preview != NULL) 
	{     
		//获得当前工作部件tag     
		tag_t work_part = UF_ASSEM_ask_work_part();     
		//由模型视图名字得到tag     
		tag_t view_tag = NULL_TAG;     
		int err = UF_VIEW_ask_tag_of_view_name("TFR_ISO", &view_tag);    
		err = sizeof(PVT_view_prefs_s*);     
		PVT_view_prefs_s* view_pref = (PVT_view_prefs_s*)malloc(1000);//     
		memset(view_pref, 0, 1000);     
		if (PVT_init_view_preferences != NULL)     
		{         
			//初始化预览参数         
			PVT_init_view_preferences(view_pref);         
			int errorCode = 0;         
			PVT_create_preview(view_tag, "", 1, &work_part, 0, NULL, false, true, view_pref, PVT_cancel_type(1), true, &errorCode);
		} 
	}  

	//查找部件名字
	char partname[MAX_FSPEC_BUFSIZE + 1];
	UF_PART_ask_part_name(UF_PART_ask_display_part(), partname);

	string name = partname;
	int pos = name.find_last_of('\\');
	string s1(name.substr(pos + 1));
	//分割字符串(只读取part名)
	string s2(s1.substr(0, s1.find(".")));
	string panthqian = "D:\\nxopen_demo\\";
	string panthhou = ".png";
	string panth = panthqian + s2 + panthhou;

	char* filename = (char*)panth.c_str();
	//char *filename = "D:\\part1\\ugapi.png";//输出图片的路径名字

	UF_DISP_create_image(filename, UF_DISP_PNG, UF_DISP_WHITE);
	UF_terminate();

第三种方法:因为我不想让弹出现对话框,所以以上方法不太好,因此我想到应用UF_DISP_create_image函数配合视图进行截屏,反正我感觉还凑合。最起码在导出数控编程程序清单时不用弹对话框。

清单内容,如下:我想要达到一下图片中插入图片的内容

//用户定义
#include <uf.h>
#include <UF_DISP.h>
#include <uf_view.h>
#include <uf_assem.h>
#include <uf_part.h>

#include <uf_defs.h>
#include <NXOpen/NXException.hxx>
#include <NXOpen/Session.hxx>
#include <NXOpen/ModelingView.hxx>
#include <NXOpen/ModelingViewCollection.hxx>
#include <NXOpen/Part.hxx>
#include <NXOpen/PartCollection.hxx>
#include <NXOpen/View.hxx>



	UF_initialize();
	//初始化
	NXOpen::Session *theSession = NXOpen::Session::GetSession();
	NXOpen::Part *workPart(theSession->Parts()->Work());
	NXOpen::Part *displayPart(theSession->Parts()->Display());

	//调整大小为适合窗口的0.7
	tag_t tagView;
	UF_VIEW_ask_work_view(&tagView);
	UF_VIEW_fit_view(tagView, 0.7);//if NULL_TAG, work view is used

	//   Menu: 定向视图(R)->正三轴测图(T)
	workPart->ModelingViews()->WorkView()->Orient(NXOpen::View::CannedTrimetric, NXOpen::View::ScaleAdjustmentFit);
	//查找部件名字
	char partname[MAX_FSPEC_BUFSIZE + 1];
	UF_PART_ask_part_name(UF_PART_ask_display_part(), partname);

	string name = partname;
	int pos = name.find_last_of('\\');
	string s1(name.substr(pos + 1));
	//分割字符串(只读取part名)
	string s2(s1.substr(0, s1.find(".")));
	string panthqian = "D:\\nxopen_demo\\";
	string panthhou = "正三轴测图.png";
	string panth = panthqian + s2 + panthhou;
	char* filename = (char*)panth.c_str();
	//判断图片是否已经创建,若创建直接替换
	int partNewFullNametatus = 0;//0文件存在,1文件不存在
	UF_CFI_ask_file_exist(filename, &partNewFullNametatus); //partNewFullNametatus 检测文件是否存在,0为存在,1为不存在
															 //partNewFullNametatus 检测文件是否存在,0为存在,1为不存在IsDelectValue																  
	if (partNewFullNametatus == 0)
	{
		int DeleteFile = remove(filename);
	}
	UF_DISP_create_image(filename, UF_DISP_PNG, UF_DISP_WHITE);

	//   Menu: 定向视图(R)->俯视图(O)
	workPart->ModelingViews()->WorkView()->Orient(NXOpen::View::CannedTop, NXOpen::View::ScaleAdjustmentFit);
	string panthhou2 = "O_XY.png";
	string panth2 = panthqian + s2 + panthhou2;
	char* filename2 = (char*)panth2.c_str();
	//判断图片是否已经创建,若创建直接替换
	int partNewFullNametatus2 = 0;//0文件存在,1文件不存在
	UF_CFI_ask_file_exist(filename2, &partNewFullNametatus2); //partNewFullNametatus 检测文件是否存在,0为存在,1为不存在
															 //partNewFullNametatus 检测文件是否存在,0为存在,1为不存在IsDelectValue																  
	if (partNewFullNametatus2 == 0)
	{
		int DeleteFile = remove(filename2);
	}
	UF_DISP_create_image(filename2, UF_DISP_PNG, UF_DISP_WHITE);

	//   Menu: 定向视图(R)->左视图(L)
	workPart->ModelingViews()->WorkView()->Orient(NXOpen::View::CannedLeft, NXOpen::View::ScaleAdjustmentFit);

	string panthhou3 = "O_YZ.png";
	string panth3 = panthqian + s2 + panthhou3;
	char* filename3 = (char*)panth3.c_str();
	//判断图片是否已经创建,若创建直接替换
	int partNewFullNametatus3 = 0;//0文件存在,1文件不存在
	UF_CFI_ask_file_exist(filename3, &partNewFullNametatus3); //partNewFullNametatus 检测文件是否存在,0为存在,1为不存在
															 //partNewFullNametatus 检测文件是否存在,0为存在,1为不存在IsDelectValue																  
	if (partNewFullNametatus3 == 0)
	{
		int DeleteFile = remove(filename3);
	}
	UF_DISP_create_image(filename3, UF_DISP_PNG, UF_DISP_WHITE);

	UF_terminate();

以上是截图后的图片

<think>好的,用户想要了解如何将C++中的鼠标光标屏幕坐标转换为UG窗口坐标,并希望得到完整的代码。首先,我需要明确几个关键点:屏幕坐标和窗口坐标的区别,以及如何通过Windows API或UG NX的API来实现这种转换。 首先,屏幕坐标是相对于整个屏幕左上角的坐标,而窗口坐标是相对于特定窗口客户区的左上角。因此,转换的关键在于获取窗口的位置和客户区的偏移。 接下来,我需要考虑用户提到的“UG窗口”是否指的是UG NX软件的窗口。如果是的话,可能需要使用UG NX的API来获取窗口信息。不过,UG NX的API文档可能不是公开的,或者用户可能没有访问权限。因此,可能需要依赖标准的Windows API来实现。 基本的步骤应该是: 1. 获取鼠标的屏幕坐标,可以使用GetCursorPos函数。 2. 找到目标窗口的句柄,比如使用FindWindow或用户提供的窗口句柄。 3. 将屏幕坐标转换为窗口客户区坐标,使用ScreenToClient函数。 不过,需要考虑窗口的边框和标题栏等非客户区的影响。ScreenToClient会自动处理这些,将屏幕坐标转换为客户区坐标。 如果用户使用的是MFC或其他框架,可能有更简便的方法,但这里应使用纯Windows API以保证通用性。 然后,我需要编写示例代码,确保包含必要的头文件和库,比如Windows.h。代码中需要处理可能的错误,比如无效的窗口句柄。 另外,如果用户使用的是UG NX的特定环境,可能需要使用UGOpen的API,比如UF_UI_get_default_parent()来获取主窗口句柄,或者UF_UI_lock_ug_access等函数来确保线程安全。这部分可能需要更详细的UG API知识,但考虑到用户可能没有相关文档,保持使用标准Windows API更稳妥。 最后,需要测试代码,确保转换正确,并提醒用户注意窗口句柄的有效性和可能的坐标偏移问题。</think>要实现C++中鼠标屏幕坐标到UG窗口坐标的转换,需通过Windows API完成坐标转换。以下是详细实现步骤和完整代码示例: ```cpp #include <Windows.h> // 函数声明 POINT ConvertScreenToUGWindow(HWND hUgWindow); int main() { // 获取UG窗口句柄(需根据实际情况修改) HWND hUgWindow = FindWindow(L"UG窗口类名", nullptr); if (!hUgWindow) { MessageBox(nullptr, L"未找到UG窗口", L"错误", MB_OK); return 1; } // 执行坐标转换 POINT clientPoint = ConvertScreenToUGWindow(hUgWindow); // 输出结果(示例) printf("转换后的窗口坐标:X=%d, Y=%d\n", clientPoint.x, clientPoint.y); return 0; } POINT ConvertScreenToUGWindow(HWND hUgWindow) { POINT screenPoint; // 屏幕坐标 POINT clientPoint; // 窗口坐标 // 步骤1:获取当前鼠标屏幕坐标 GetCursorPos(&screenPoint); // 步骤2:转换为UG窗口客户区坐标 ScreenToClient(hUgWindow, &screenPoint); clientPoint = screenPoint; return clientPoint; } ``` 关键实现原理: 1. **坐标体系差异** - 屏幕坐标系:以屏幕左上角为原点 $(0,0)$ - 窗口坐标系:以窗口客户区左上角为原点 $(0,0)$ 2. **核心API函数** - `GetCursorPos`:获取当前光标屏幕坐标 - `ScreenToClient`:执行坐标转换计算 - `FindWindow`:获取目标窗口句柄 3. **注意事项** - 必须确保窗口句柄有效 - 窗口不能处于最小化状态 - 多显示器环境需注意坐标范围 - 如果使用UG NX API开发,需先调用: ```cpp UF_initialize(); // 初始化UG环境 HWND hUgWindow = (HWND)UF_UI_get_default_parent(); ``` 坐标转换数学公式: $$ \begin{cases} window\_x = screen\_x - window\_left\_border \\ window\_y = screen\_y - window\_top\_border - title\_bar\_height \end{cases} $$ 建议在实际开发中增加以下处理: 1. 错误检查机制 2. 窗口状态判断 3. 多线程同步(如果使用UG API) 4. 坐标系边界校验 如果开发UG NX二次应用,推荐结合UG/Open API使用: ```cpp #include <uf.h> #include <uf_ui.h> extern "C" DllExport void ufusr(char* param, int* retcode, int paramLen) { UF_initialize(); HWND hUgMainWindow = (HWND)UF_UI_get_default_parent(); POINT ugPoint = ConvertScreenToUGWindow(hUgMainWindow); UF_terminate(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白雪公主的后妈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值