DLL - How to Write

本文介绍了动态链接库(DLL)的基本概念,包括两种链接方式:加载时动态链接和运行时动态链接。详细讨论了如何选择合适的链接方式,并解释了DLL入口点的作用及如何导出DLL函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:

http://www.tutorialspoint.com/dll/dll_writing.htm

 

First, we will discuss the issues and the requirements that you should consider while developing your own DLLs.

Types of DLLs

When you load a DLL in an application, two methods of linking let you call the exported DLL functions. The two methods of linking are −

  • load-time dynamic linking, and
  • run-time dynamic linking.

Load-time dynamic linking

In load-time dynamic linking, an application makes explicit calls to the exported DLL functions like local functions. To use load-time dynamic linking, provide a header (.h) file and an import library (.lib) file, when you compile and link the application. When you do this, the linker will provide the system with the information that is required to load the DLL and resolve the exported DLL function locations at load time.

Runtime dynamic linking

In runtime dynamic linking, an application calls either the LoadLibrary function or the LoadLibraryEx function to load the DLL at runtime. After the DLL is successfully loaded, you use the GetProcAddress function, to obtain the address of the exported DLL function that you want to call. When you use runtime dynamic linking, you do not need an import library file.

The following list describes the application criteria for choosing between load-time dynamic linking and runtime dynamic linking −

  • Startup performance − If the initial startup performance of the application is important, you should use run-time dynamic linking.

  • Ease of use − In load-time dynamic linking, the exported DLL functions are like local functions. It helps you call these functions easily.

  • Application logic − In runtime dynamic linking, an application can branch to load different modules as required. This is important when you develop multiple-language versions.

The DLL Entry Point

When you create a DLL, you can optionally specify an entry point function. The entry point function is called when processes or threads attach themselves to the DLL or detach themselves from the DLL. You can use the entry point function to initialize or destroy data structures as required by the DLL.

Additionally, if the application is multithreaded, you can use thread local storage (TLS) to allocate memory that is private to each thread in the entry point function. The following code is an example of the DLL entry point function.

BOOL APIENTRY DllMain(
   HANDLE hModule,	   // Handle to DLL module 
   DWORD ul_reason_for_call, 
   LPVOID lpReserved )     // Reserved
{
   switch ( ul_reason_for_call )
   {
      case DLL_PROCESS_ATTACHED:
      // A process is loading the DLL.
      break;
      
      case DLL_THREAD_ATTACHED:
      // A process is creating a new thread.
      break;
      
      case DLL_THREAD_DETACH:
      // A thread exits normally.
      break;
      
      case DLL_PROCESS_DETACH:
      // A process unloads the DLL.
      break;
   }
   return TRUE;
}

When the entry point function returns a FALSE value, the application will not start if you are using load-time dynamic linking. If you are using runtime dynamic linking, only the individual DLL will not load.

The entry point function should only perform simple initialization tasks and should not call any other DLL loading or termination functions. For example, in the entry point function, you should not directly or indirectly call the LoadLibrary function or the LoadLibraryEx function. Additionally, you should not call the FreeLibrary function when the process is terminating.

WARNING − In multithreaded applications, make sure that access to the DLL global data is synchronized (thread safe) to avoid possible data corruption. To do this, use TLS to provide unique data for each thread.

Exporting DLL Functions

To export DLL functions, you can either add a function keyword to the exported DLL functions or create a module definition (.def) file that lists the exported DLL functions.

To use a function keyword, you must declare each function that you want to export with the following keyword −

__declspec(dllexport)

To use exported DLL functions in the application, you must declare each function that you want to import with the following keyword −

__declspec(dllimport)

Typically, you would use one header file having define statement and an ifdef statement to separate the export statement and the import statement.

You can also use a module definition file to declare exported DLL functions. When you use a module definition file, you do not have to add the function keyword to the exported DLL functions. In the module definition file, you declare the LIBRARY statement and the EXPORTS statement for the DLL. The following code is an example of a definition file.

// SampleDLL.def
//
LIBRARY "sampleDLL"

EXPORTS
   HelloWorld

Write a Sample DLL

In Microsoft Visual C++ 6.0, you can create a DLL by selecting either the Win32 Dynamic-Link Library project type or the MFC AppWizard (dll) project type.

The following code is an example of a DLL that was created in Visual C++ by using the Win32 Dynamic-Link Library project type.

// SampleDLL.cpp

#include "stdafx.h"
#define EXPORTING_DLL
#include "sampleDLL.h"

BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
   return TRUE;
}

void HelloWorld()
{
   MessageBox( NULL, TEXT("Hello World"), 
   TEXT("In a DLL"), MB_OK);
}
// File: SampleDLL.h
//
#ifndef INDLL_H
#define INDLL_H

   #ifdef EXPORTING_DLL
      extern __declspec(dllexport) void HelloWorld() ;
   #else
      extern __declspec(dllimport) void HelloWorld() ;
   #endif

#endif

Calling a Sample DLL

The following code is an example of a Win32 Application project that calls the exported DLL function in the SampleDLL DLL.

// SampleApp.cpp 

#include "stdafx.h"
#include "sampleDLL.h"

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{ 	
   HelloWorld();
   return 0;
}

NOTE − In load-time dynamic linking, you must link the SampleDLL.lib import library that is created when you build the SampleDLL project.

In runtime dynamic linking, you use code that is similar to the following code to call the SampleDLL.dll exported DLL function.

...
typedef VOID (*DLLPROC) (LPTSTR);
...
HINSTANCE hinstDLL;
DLLPROC HelloWorld;
BOOL fFreeDLL;

hinstDLL = LoadLibrary("sampleDLL.dll");

if (hinstDLL != NULL)
{
   HelloWorld = (DLLPROC) GetProcAddress(hinstDLL, "HelloWorld");
	
   if (HelloWorld != NULL)
      (HelloWorld);

   fFreeDLL = FreeLibrary(hinstDLL);
}
...

When you compile and link the SampleDLL application, the Windows operating system searches for the SampleDLL DLL in the following locations in this order −

  • The application folder

  • The current folder

  • The Windows system folder (The GetSystemDirectory function returns the path of the Windows system folder).

  • The Windows folder (The GetWindowsDirectory function returns the path of the Windows folder).

 

我正在学习NX二次开发,用的是Visual Studio 2019,ug版本是12.0,开发平台是c++,uf函数为主nxopen函数为辅。需要你辅助我开发,重点注意开发模版是c++,优先使用uf函数,要求你先搞清楚你提供给我的代码真实有效性,语句与标点符号的正确位置,避免出现ug12.0没有提供的接口成员出现!确保所有方法调用都符合 NX12 的 API 签名,深度思考下再回答,每次回答前先回顾下前面的所有对话避免问题重复出现,每行代码都用中文注解具体意思与作用。头文件:“//============================================================================== // WARNING!! This file is overwritten by the Block Styler while generating // the automation code. Any modifications to this file will be lost after // generating the code again. // // Filename: D:\NXopen\BaiduSyncdisk\studio\jiamiceshi\ui\jiamiceshi.hpp // // This file was generated by the NX Block Styler // Created by: MICH-ROG // Version: NX 12 // Date: 08-19-2025 (Format: mm-dd-yyyy) // Time: 14:36 // //============================================================================== #ifndef JIAMICESHI_H_INCLUDED #define JIAMICESHI_H_INCLUDED //------------------------------------------------------------------------------ //These includes are needed for the following template code //------------------------------------------------------------------------------ #include <uf_defs.h> #include <uf_ui_types.h> #include #include <NXOpen/Session.hxx> #include <NXOpen/UI.hxx> #include <NXOpen/NXMessageBox.hxx> #include <NXOpen/Callback.hxx> #include <NXOpen/NXException.hxx> #include <NXOpen/BlockStyler_UIBlock.hxx> #include <NXOpen/BlockStyler_BlockDialog.hxx> #include <NXOpen/BlockStyler_PropertyList.hxx> #include <NXOpen/BlockStyler_Group.hxx> #include <NXOpen/BlockStyler_SelectObject.hxx> #include <NXOpen/BlockStyler_ExpressionBlock.hxx> //------------------------------------------------------------------------------ // Namespaces needed for following template //------------------------------------------------------------------------------ using namespace std; using namespace NXOpen; using namespace NXOpen::BlockStyler; class DllExport jiamiceshi { // class members public: static Session *theSession; static UI *theUI; jiamiceshi(); ~jiamiceshi(); int Show(); //----------------------- BlockStyler Callback Prototypes --------------------- // The following member function prototypes define the callbacks // specified in your BlockStyler dialog. The empty implementation // of these prototypes is provided in the jiamiceshi.cpp file. // You are REQUIRED to write the implementation for these functions. //------------------------------------------------------------------------------ void initialize_cb(); void dialogShown_cb(); int apply_cb(); int ok_cb(); int update_cb(NXOpen::BlockStyler::UIBlock* block); PropertyList* GetBlockProperties(const char *blockID); private: const char* theDlxFileName; NXOpen::BlockStyler::BlockDialog* theDialog; NXOpen::BlockStyler::Group* group0;// Block type: Group NXOpen::BlockStyler::SelectObject* selection0;// Block type: Selection NXOpen::BlockStyler::ExpressionBlock* expression0;// Block type: Expression }; #endif //JIAMICESHI_H_INCLUDED ”源文件cpp:“//============================================================================== // WARNING!! This file is overwritten by the Block UI Styler while generating // the automation code. Any modifications to this file will be lost after // generating the code again. // // Filename: D:\NXopen\BaiduSyncdisk\studio\jiamiceshi\ui\jiamiceshi.cpp // // This file was generated by the NX Block UI Styler // Created by: MICH-ROG // Version: NX 12 // Date: 08-19-2025 (Format: mm-dd-yyyy) // Time: 14:36 (Format: hh-mm) // //============================================================================== //============================================================================== // Purpose: This TEMPLATE file contains C++ source to guide you in the // construction of your Block application dialog. The generation of your // dialog file (.dlx extension) is the first step towards dialog construction // within NX. You must now create a NX Open application that // utilizes this file (.dlx). // // The information in this file provides you with the following: // // 1. Help on how to load and display your Block UI Styler dialog in NX // using APIs provided in NXOpen.BlockStyler namespace // 2. The empty callback methods (stubs) associated with your dialog items // have also been placed in this file. These empty methods have been // created simply to start you along with your coding requirements. // The method name, argument list and possible return values have already // been provided for you. //============================================================================== //------------------------------------------------------------------------------ //These includes are needed for the following template code //------------------------------------------------------------------------------ #include “jiamiceshi.hpp” using namespace NXOpen; using namespace NXOpen::BlockStyler; //------------------------------------------------------------------------------ // Initialize static variables //------------------------------------------------------------------------------ Session *(jiamiceshi::theSession) = NULL; UI *(jiamiceshi::theUI) = NULL; //------------------------------------------------------------------------------ // Constructor for NX Styler class //------------------------------------------------------------------------------ jiamiceshi::jiamiceshi() { try { // Initialize the NX Open C++ API environment jiamiceshi::theSession = NXOpen::Session::GetSession(); jiamiceshi::theUI = UI::GetUI(); theDlxFileName = “jiamiceshi.dlx”; theDialog = jiamiceshi::theUI->CreateDialog(theDlxFileName); // Registration of callback functions theDialog->AddApplyHandler(make_callback(this, &jiamiceshi::apply_cb)); theDialog->AddOkHandler(make_callback(this, &jiamiceshi::ok_cb)); theDialog->AddUpdateHandler(make_callback(this, &jiamiceshi::update_cb)); theDialog->AddInitializeHandler(make_callback(this, &jiamiceshi::initialize_cb)); theDialog->AddDialogShownHandler(make_callback(this, &jiamiceshi::dialogShown_cb)); } catch(exception& ex) { //---- Enter your exception handling code here ----- throw; } } //------------------------------------------------------------------------------ // Destructor for NX Styler class //------------------------------------------------------------------------------ jiamiceshi::~jiamiceshi() { if (theDialog != NULL) { delete theDialog; theDialog = NULL; } } //------------------------------- DIALOG LAUNCHING --------------------------------- // // Before invoking this application one needs to open any part/empty part in NX // because of the behavior of the blocks. // // Make sure the dlx file is in one of the following locations: // 1.) From where NX session is launched // 2.) $UGII_USER_DIR/application // 3.) For released applications, using UGII_CUSTOM_DIRECTORY_FILE is highly // recommended. This variable is set to a full directory path to a file // containing a list of root directories for all custom applications. // e.g., UGII_CUSTOM_DIRECTORY_FILE=$UGII_BASE_DIR\ugii\menus\custom_dirs.dat // // You can create the dialog using one of the following way: // // 1. USER EXIT // // 1) Create the Shared Library – Refer “Block UI Styler programmer’s guide” // 2) Invoke the Shared Library through File->Execute->NX Open menu. // //------------------------------------------------------------------------------ extern “C” DllExport void ufusr(char *param, int *retcod, int param_len) { jiamiceshi *thejiamiceshi = NULL; try { thejiamiceshi = new jiamiceshi(); // The following method shows the dialog immediately thejiamiceshi->Show(); } catch(exception& ex) { //---- Enter your exception handling code here ----- jiamiceshi::theUI->NXMessageBox()->Show(“Block Styler”, NXOpen::NXMessageBox::DialogTypeError, ex.what()); } if(thejiamiceshi != NULL) { delete thejiamiceshi; thejiamiceshi = NULL; } } //------------------------------------------------------------------------------ // This method specifies how a shared image is unloaded from memory // within NX. This method gives you the capability to unload an // internal NX Open application or user exit from NX. Specify any // one of the three constants as a return value to determine the type // of unload to perform: // // // Immediately : unload the library as soon as the automation program has completed // Explicitly : unload the library from the “Unload Shared Image” dialog // AtTermination : unload the library when the NX session terminates // // // NOTE: A program which associates NX Open applications with the menubar // MUST NOT use this option since it will UNLOAD your NX Open application image // from the menubar. //------------------------------------------------------------------------------ extern “C” DllExport int ufusr_ask_unload() { //return (int)Session::LibraryUnloadOptionExplicitly; return (int)Session::LibraryUnloadOptionImmediately; //return (int)Session::LibraryUnloadOptionAtTermination; } //------------------------------------------------------------------------------ // Following method cleanup any housekeeping chores that may be needed. // This method is automatically called by NX. //------------------------------------------------------------------------------ extern “C” DllExport void ufusr_cleanup(void) { try { //---- Enter your callback code here ----- } catch(exception& ex) { //---- Enter your exception handling code here ----- jiamiceshi::theUI->NXMessageBox()->Show(“Block Styler”, NXOpen::NXMessageBox::DialogTypeError, ex.what()); } } int jiamiceshi::Show() { try { theDialog->Show(); } catch(exception& ex) { //---- Enter your exception handling code here ----- jiamiceshi::theUI->NXMessageBox()->Show(“Block Styler”, NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return 0; } //------------------------------------------------------------------------------ //---------------------Block UI Styler Callback Functions-------------------------- //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //Callback Name: initialize_cb //------------------------------------------------------------------------------ void jiamiceshi::initialize_cb() { try { group0 = dynamic_castNXOpen::BlockStyler::Group*(theDialog->TopBlock()->FindBlock(“group0”)); selection0 = dynamic_castNXOpen::BlockStyler::SelectObject*(theDialog->TopBlock()->FindBlock(“selection0”)); expression0 = dynamic_castNXOpen::BlockStyler::ExpressionBlock*(theDialog->TopBlock()->FindBlock(“expression0”)); } catch(exception& ex) { //---- Enter your exception handling code here ----- jiamiceshi::theUI->NXMessageBox()->Show(“Block Styler”, NXOpen::NXMessageBox::DialogTypeError, ex.what()); } } //------------------------------------------------------------------------------ //Callback Name: dialogShown_cb //This callback is executed just before the dialog launch. Thus any value set //here will take precedence and dialog will be launched showing that value. //------------------------------------------------------------------------------ void jiamiceshi::dialogShown_cb() { try { //---- Enter your callback code here ----- } catch(exception& ex) { //---- Enter your exception handling code here ----- jiamiceshi::theUI->NXMessageBox()->Show(“Block Styler”, NXOpen::NXMessageBox::DialogTypeError, ex.what()); } } //------------------------------------------------------------------------------ //Callback Name: apply_cb //------------------------------------------------------------------------------ int jiamiceshi::apply_cb() { int errorCode = 0; try { //---- Enter your callback code here ----- } catch(exception& ex) { //---- Enter your exception handling code here ----- errorCode = 1; jiamiceshi::theUI->NXMessageBox()->Show(“Block Styler”, NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return errorCode; } //------------------------------------------------------------------------------ //Callback Name: update_cb //------------------------------------------------------------------------------ int jiamiceshi::update_cb(NXOpen::BlockStyler::UIBlock* block) { try { if(block == selection0) { //---------Enter your code here----------- } else if(block == expression0) { //---------Enter your code here----------- } } catch(exception& ex) { //---- Enter your exception handling code here ----- jiamiceshi::theUI->NXMessageBox()->Show(“Block Styler”, NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return 0; } //------------------------------------------------------------------------------ //Callback Name: ok_cb //------------------------------------------------------------------------------ int jiamiceshi::ok_cb() { int errorCode = 0; try { errorCode = apply_cb(); } catch(exception& ex) { //---- Enter your exception handling code here ----- errorCode = 1; jiamiceshi::theUI->NXMessageBox()->Show(“Block Styler”, NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return errorCode; } //------------------------------------------------------------------------------ //Function Name: GetBlockProperties //Description: Returns the propertylist of the specified BlockID //------------------------------------------------------------------------------ PropertyList* jiamiceshi::GetBlockProperties(const char *blockID) { return theDialog->GetBlockProperties(blockID); } ”我需要给这个功能做使用日期限制,到限制日期就不能用了。每行代码中文注解
08-20
依然不能准确的找到最低点高于z0的实体我把完整的代码发你检查下,现在只解决(block == gtbody)这部分的问题,仔细检查问题,//============================================================================== // WARNING!! This file is overwritten by the Block Styler while generating // the automation code. Any modifications to this file will be lost after // generating the code again. // // Filename: D:\NXopen\BaiduSyncdisk\Application\gaiyansetool.hpp // // This file was generated by the NX Block Styler // Created by: MICH-ROG // Version: NX 12 // Date: 07-31-2025 (Format: mm-dd-yyyy) // Time: 16:55 // //============================================================================== #ifndef GAIYANSETOOL_H_INCLUDED #define GAIYANSETOOL_H_INCLUDED //------------------------------------------------------------------------------ //These includes are needed for the following template code //------------------------------------------------------------------------------ #include <uf_defs.h> #include <uf_ui_types.h> #include <iostream> #include <NXOpen/Session.hxx> #include <NXOpen/UI.hxx> #include <NXOpen/NXMessageBox.hxx> #include <NXOpen/Callback.hxx> #include <NXOpen/NXException.hxx> #include <NXOpen/BlockStyler_UIBlock.hxx> #include <NXOpen/BlockStyler_BlockDialog.hxx> #include <NXOpen/BlockStyler_PropertyList.hxx> #include <NXOpen/BlockStyler_Group.hxx> #include <NXOpen/BlockStyler_Enumeration.hxx> #include <NXOpen/BlockStyler_FaceCollector.hxx> #include <NXOpen/BlockStyler_ObjectColorPicker.hxx> #include <NXOpen/BlockStyler_Button.hxx> #include "uf_all.h" #include "HuNXOpen.h" #include <algorithm> // 包含std::sort算法 #include <set> // 包含std::set容器 #include <vector> // 包含std::vector容器 #include <cmath> // 包含数学函数 #include <limits> // 包含数值极限 #include <memory> // 包含智能指针 #include <NXOpen/Part.hxx> #include <NXOpen/Body.hxx> #include <NXOpen/Face.hxx> #include <NXOpen/Point.hxx> #include <NXOpen/Direction.hxx> #include <NXOpen/Unit.hxx> #include <vector> #include <cmath> #include <uf_part.h> #include <cfloat> #include <uf_eval.h> //------------------------------------------------------------------------------ // Namespaces needed for following template //------------------------------------------------------------------------------ using namespace std; using namespace NXOpen; using namespace NXOpen::BlockStyler; class DllExport gaiyansetool { // class members public: static Session *theSession; static UI *theUI; gaiyansetool(); ~gaiyansetool(); int Show(); //----------------------- BlockStyler Callback Prototypes --------------------- // The following member function prototypes define the callbacks // specified in your BlockStyler dialog. The empty implementation // of these prototypes is provided in the gaiyansetool.cpp file. // You are REQUIRED to write the implementation for these functions. //------------------------------------------------------------------------------ void initialize_cb(); void dialogShown_cb(); int apply_cb(); int ok_cb(); int update_cb(NXOpen::BlockStyler::UIBlock* block); PropertyList* GetBlockProperties(const char *blockID); private: const char* theDlxFileName; NXOpen::BlockStyler::BlockDialog* theDialog; NXOpen::BlockStyler::Group* group1;// Block type: Group NXOpen::BlockStyler::Enumeration* enum0;// Block type: Enumeration NXOpen::BlockStyler::Group* group0;// Block type: Group NXOpen::BlockStyler::FaceCollector* face1;// Block type: Face Collector NXOpen::BlockStyler::Group* group;// Block type: Group NXOpen::BlockStyler::ObjectColorPicker* color1;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* color2;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* color3;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* color4;// Block type: Color Picker NXOpen::BlockStyler::Button* bu1;// Block type: Button NXOpen::BlockStyler::Button* bu2;// Block type: Button NXOpen::BlockStyler::Button* bu3;// Block type: Button NXOpen::BlockStyler::Button* bu4;// Block type: Button NXOpen::BlockStyler::ObjectColorPicker* color5;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* color6;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* color7;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* color8;// Block type: Color Picker NXOpen::BlockStyler::Button* bu5;// Block type: Button NXOpen::BlockStyler::Button* bu6;// Block type: Button NXOpen::BlockStyler::Button* bu7;// Block type: Button NXOpen::BlockStyler::Button* bu8;// Block type: Button NXOpen::BlockStyler::ObjectColorPicker* color9;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* color10;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* color11;// Block type: Color Picker NXOpen::BlockStyler::ObjectColorPicker* color12;// Block type: Color Picker NXOpen::BlockStyler::Button* bu9;// Block type: Button NXOpen::BlockStyler::Button* bu10;// Block type: Button NXOpen::BlockStyler::Button* bu11;// Block type: Button NXOpen::BlockStyler::Button* bu12;// Block type: Button NXOpen::BlockStyler::Group* group2;// Block type: Group NXOpen::BlockStyler::Button* dbpface;// Block type: Button NXOpen::BlockStyler::Button* gtbody;// Block type: Button NXOpen::BlockStyler::Button* arcface;// Block type: Button NXOpen::BlockStyler::Button* gaodipoints;// Block type: Button NXOpen::BlockStyler::Button* Keyway1;// Block type: Button }; #endif //GAIYANSETOOL_H_INCLUDED 以上是头文件,以下是源文件,//============================================================================== // WARNING!! This file is overwritten by the Block UI Styler while generating // the automation code. Any modifications to this file will be lost after // generating the code again. // // Filename: D:\NXopen\BaiduSyncdisk\Application\gaiyansetool.cpp // // This file was generated by the NX Block UI Styler // Created by: MICH-ROG // Version: NX 12 // Date: 07-31-2025 (Format: mm-dd-yyyy) // Time: 16:55 (Format: hh-mm) // //============================================================================== //============================================================================== // Purpose: This TEMPLATE file contains C++ source to guide you in the // construction of your Block application dialog. The generation of your // dialog file (.dlx extension) is the first step towards dialog construction // within NX. You must now create a NX Open application that // utilizes this file (.dlx). // // The information in this file provides you with the following: // // 1. Help on how to load and display your Block UI Styler dialog in NX // using APIs provided in NXOpen.BlockStyler namespace // 2. The empty callback methods (stubs) associated with your dialog items // have also been placed in this file. These empty methods have been // created simply to start you along with your coding requirements. // The method name, argument list and possible return values have already // been provided for you. //============================================================================== //------------------------------------------------------------------------------ //These includes are needed for the following template code //------------------------------------------------------------------------------ #include "gaiyansetool.hpp" using namespace NXOpen; using namespace NXOpen::BlockStyler; // 辅助结构体存储面信息 struct FaceInfo { TaggedObject* faceObj; double centerZ; int faceType; double radius; }; //------------------------------------------------------------------------------ // Initialize static variables //------------------------------------------------------------------------------ Session *(gaiyansetool::theSession) = NULL; UI *(gaiyansetool::theUI) = NULL; //------------------------------------------------------------------------------ // Constructor for NX Styler class //------------------------------------------------------------------------------ gaiyansetool::gaiyansetool() { try { // Initialize the NX Open C++ API environment gaiyansetool::theSession = NXOpen::Session::GetSession(); gaiyansetool::theUI = UI::GetUI(); theDlxFileName = "gaiyansetool.dlx"; theDialog = gaiyansetool::theUI->CreateDialog(theDlxFileName); // Registration of callback functions theDialog->AddApplyHandler(make_callback(this, &gaiyansetool::apply_cb)); theDialog->AddOkHandler(make_callback(this, &gaiyansetool::ok_cb)); theDialog->AddUpdateHandler(make_callback(this, &gaiyansetool::update_cb)); theDialog->AddInitializeHandler(make_callback(this, &gaiyansetool::initialize_cb)); theDialog->AddDialogShownHandler(make_callback(this, &gaiyansetool::dialogShown_cb)); } catch(exception& ex) { //---- Enter your exception handling code here ----- throw; } } //------------------------------------------------------------------------------ // Destructor for NX Styler class //------------------------------------------------------------------------------ gaiyansetool::~gaiyansetool() { if (theDialog != NULL) { delete theDialog; theDialog = NULL; } } //------------------------------- DIALOG LAUNCHING --------------------------------- // // Before invoking this application one needs to open any part/empty part in NX // because of the behavior of the blocks. // // Make sure the dlx file is in one of the following locations: // 1.) From where NX session is launched // 2.) $UGII_USER_DIR/application // 3.) For released applications, using UGII_CUSTOM_DIRECTORY_FILE is highly // recommended. This variable is set to a full directory path to a file // containing a list of root directories for all custom applications. // e.g., UGII_CUSTOM_DIRECTORY_FILE=$UGII_BASE_DIR\ugii\menus\custom_dirs.dat // // You can create the dialog using one of the following way: // // 1. USER EXIT // // 1) Create the Shared Library -- Refer "Block UI Styler programmer's guide" // 2) Invoke the Shared Library through File->Execute->NX Open menu. // //------------------------------------------------------------------------------ extern "C" DllExport void ufusr(char *param, int *retcod, int param_len) { gaiyansetool *thegaiyansetool = NULL; try { UF_initialize(); //开发的许可函数,初始化 thegaiyansetool = new gaiyansetool(); // The following method shows the dialog immediately thegaiyansetool->Show(); } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } if(thegaiyansetool != NULL) { delete thegaiyansetool; thegaiyansetool = NULL; }UF_terminate(); //释放许可函数,结束化 } //------------------------------------------------------------------------------ // This method specifies how a shared image is unloaded from memory // within NX. This method gives you the capability to unload an // internal NX Open application or user exit from NX. Specify any // one of the three constants as a return value to determine the type // of unload to perform: // // // Immediately : unload the library as soon as the automation program has completed // Explicitly : unload the library from the "Unload Shared Image" dialog // AtTermination : unload the library when the NX session terminates // // // NOTE: A program which associates NX Open applications with the menubar // MUST NOT use this option since it will UNLOAD your NX Open application image // from the menubar. //------------------------------------------------------------------------------ extern "C" DllExport int ufusr_ask_unload() { //return (int)Session::LibraryUnloadOptionExplicitly; return (int)Session::LibraryUnloadOptionImmediately; //return (int)Session::LibraryUnloadOptionAtTermination; } //------------------------------------------------------------------------------ // Following method cleanup any housekeeping chores that may be needed. // This method is automatically called by NX. //------------------------------------------------------------------------------ extern "C" DllExport void ufusr_cleanup(void) { try { //---- Enter your callback code here ----- } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } } int gaiyansetool::Show() { try { theDialog->Show(); } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return 0; } //------------------------------------------------------------------------------ //---------------------Block UI Styler Callback Functions-------------------------- //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //Callback Name: initialize_cb //------------------------------------------------------------------------------ void gaiyansetool::initialize_cb() { try { group1 = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group1")); enum0 = dynamic_cast<NXOpen::BlockStyler::Enumeration*>(theDialog->TopBlock()->FindBlock("enum0")); group0 = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group0")); face1 = dynamic_cast<NXOpen::BlockStyler::FaceCollector*>(theDialog->TopBlock()->FindBlock("face1")); group = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group")); color1 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color1")); color2 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color2")); color3 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color3")); color4 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color4")); bu1 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu1")); bu2 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu2")); bu3 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu3")); bu4 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu4")); color5 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color5")); color6 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color6")); color7 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color7")); color8 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color8")); bu5 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu5")); bu6 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu6")); bu7 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu7")); bu8 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu8")); color9 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color9")); color10 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color10")); color11 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color11")); color12 = dynamic_cast<NXOpen::BlockStyler::ObjectColorPicker*>(theDialog->TopBlock()->FindBlock("color12")); bu9 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu9")); bu10 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu10")); bu11 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu11")); bu12 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("bu12")); group2 = dynamic_cast<NXOpen::BlockStyler::Group*>(theDialog->TopBlock()->FindBlock("group2")); dbpface = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("dbpface")); gtbody = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("gtbody")); arcface = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("arcface")); gaodipoints = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("gaodipoints")); Keyway1 = dynamic_cast<NXOpen::BlockStyler::Button*>(theDialog->TopBlock()->FindBlock("Keyway1")); } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } } //------------------------------------------------------------------------------ //Callback Name: dialogShown_cb //This callback is executed just before the dialog launch. Thus any value set //here will take precedence and dialog will be launched showing that value. //------------------------------------------------------------------------------ void gaiyansetool::dialogShown_cb() { try { //---- Enter your callback code here ----- } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } } //------------------------------------------------------------------------------ //Callback Name: apply_cb //------------------------------------------------------------------------------ int gaiyansetool::apply_cb() { int errorCode = 0; try { //---- Enter your callback code here ----- } catch(exception& ex) { //---- Enter your exception handling code here ----- errorCode = 1; gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return errorCode; } //------------------------------------------------------------------------------ //Callback Name: update_cb //------------------------------------------------------------------------------ int gaiyansetool::update_cb(NXOpen::BlockStyler::UIBlock* block) { try { if (block == enum0) { //---------Enter your code here----------- } else if (block == face1) { //---------Enter your code here----------- } else if (block == color1) { //---------Enter your code here----------- } else if (block == color2) { //---------Enter your code here----------- } else if (block == color3) { //---------Enter your code here----------- } else if (block == color4) { //---------Enter your code here----------- } else if (block == bu1) { try { if (color1 != nullptr) { //获取ui枚举索引值 int iType = 0; iType = this->enum0->GetProperties()->GetEnum("Value"); // ⚙️ 1. 获取属性列表 PropertyList* colorProps = color1->GetProperties(); // 🎨 2. 获取颜色值:关键属性名为 "Value",返回整数向量 std::vector<int> colors = colorProps->GetIntegerVector("Value"); int colorID = colors[0]; // 取第一个值为颜色索引 delete colorProps;// 🧹 3. 释放属性列表内存(必须!) //char msg[256];//调试// //sprintf(msg, "%d", iType); //uc1601(msg, 1);// // ====== 以下是应用颜色到面的逻辑 ====== if (face1 != nullptr) { // 获取选中的面 std::vector<NXOpen::TaggedObject*> vFaces = face1->GetSelectedObjects(); if (vFaces.empty()) { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeError, "未选择面!"); return 0; } if (iType == 0) { // 🖌️ 遍历所有面并设置颜色 for (auto face : vFaces) { tag_t faceTag = face->Tag(); UF_OBJ_set_color(faceTag, colorID); // 应用颜色 UF_DISP_set_highlight(faceTag, 0); //高亮,0=不高亮,1=高亮 } } else { // 模式1:给选中面所在的实体设置颜色 std::set<tag_t> processedBodies;// 用于记录已处理的实体 for (auto face : vFaces) { tag_t faceTag = face->Tag(); tag_t bodyTag = NULL_TAG; // 获取面所属的实体 UF_MODL_ask_face_body(faceTag, &bodyTag); if (bodyTag != NULL_TAG && processedBodies.find(bodyTag) == processedBodies.end()) { // 清除实体上所有面的单独颜色设置(关键修复) uf_list_p_t faceList = NULL; UF_MODL_ask_body_faces(bodyTag, &faceList); int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); for (int i = 0; i < faceCount; i++) { tag_t bodyFaceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &bodyFaceTag); // 重置面颜色继承 UF_OBJ_set_color(bodyFaceTag, colorID); } UF_MODL_delete_list(&faceList); // 设置实体颜色 UF_OBJ_set_color(bodyTag, colorID); UF_DISP_set_highlight(bodyTag, 0); processedBodies.insert(bodyTag); // 添加到已处理集合 } } } // 清空选择并刷新显示 vFaces.clear(); face1->SetSelectedObjects(vFaces); UF_DISP_refresh(); } } else { theUI->NXMessageBox()->Show("MICH-明:错误提示", NXMessageBox::DialogTypeError, "color1未初始化!"); } } catch (exception& ex) { theUI->NXMessageBox()->Show("MICH-明:错误提示", NXMessageBox::DialogTypeError, ex.what()); } } // 这行结束 else if (block == bu2) { //---------Enter your code here----------- } else if (block == bu3) { //---------Enter your code here----------- } else if (block == bu4) { //---------Enter your code here----------- } else if (block == color5) { //---------Enter your code here----------- } else if (block == color6) { //---------Enter your code here----------- } else if (block == color7) { //---------Enter your code here----------- } else if (block == color8) { //---------Enter your code here----------- } else if (block == bu5) { //---------Enter your code here----------- } else if (block == bu6) { //---------Enter your code here----------- } else if (block == bu7) { //---------Enter your code here----------- } else if (block == bu8) { //---------Enter your code here----------- } else if (block == color9) { //---------Enter your code here----------- } else if (block == color10) { //---------Enter your code here----------- } else if (block == color11) { //---------Enter your code here----------- } else if (block == color12) { //---------Enter your code here----------- } else if (block == bu9) { //---------Enter your code here----------- } else if (block == bu10) { //---------Enter your code here----------- } else if (block == bu11) { //---------Enter your code here----------- } else if (block == bu12) { //---------Enter your code here----------- } else if (block == dbpface) { try { // 确保face1控件已初始化 if (face1 != nullptr) { // 1. 获取当前显示部件 tag_t displayPart = UF_PART_ask_display_part(); // 获取当前显示部件的标签 if (displayPart == NULL_TAG) // 检查是否成功获取显示部件 { theUI->NXMessageBox()->Show("MICH-明:错误提示", NXMessageBox::DialogTypeError, "未找到显示部件!"); // 显示错误消息 return 0; // 退出函数 } // 2. 收集所有可见实体 std::vector<tag_t> allObjects; // 存储可见实体的容器 tag_t currentObject = NULL_TAG; // 当前处理的对象标签 // 遍历部件中的所有实体对象 UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 获取第一个实体对象 while (currentObject != NULL_TAG) // 循环直到没有更多实体 { // 获取对象的显示属性 UF_OBJ_disp_props_t disp_props; // 声明显示属性结构体 if (UF_OBJ_ask_display_properties(currentObject, &disp_props) == 0) // 获取对象的显示属性 { // 检查对象是否显示(未隐藏) if (UF_OBJ_NOT_BLANKED == disp_props.blank_status) // 检查对象是否显示 { // 检查对象所在图层状态 int layer_status = 0; // 存储图层状态 if (UF_LAYER_ask_status(disp_props.layer, &layer_status) == 0) // 获取图层状态 { // 检查图层是否可见(活动图层或参考图层) if ( layer_status == UF_LAYER_WORK_LAYER || // 工作图层(可见可编辑) layer_status == UF_LAYER_ACTIVE_LAYER || // 活动图层(可见可选) layer_status == UF_LAYER_REFERENCE_LAYER) // 参考图层(仅可见) { allObjects.push_back(currentObject); // 将可见实体添加到容器 } } } } // 获取下一个对象 UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 继续遍历下一个实体 } if (allObjects.empty()) // 检查是否有可见实体 { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeInformation, "部件中没有可见实体!"); // 显示提示消息 return 0; // 退出函数 } // 3. 收集所有面 std::vector<TaggedObject*> allFaces; for (tag_t objectTag : allObjects) { // 获取对象上的所有面 uf_list_p_t faceList = NULL; if (UF_MODL_ask_body_faces(objectTag, &faceList) != 0) continue; int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); for (int i = 0; i < faceCount; i++) { tag_t faceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &faceTag); // 创建NXOpen::Face对象并添加到列表 NXOpen::Face* face = dynamic_cast<NXOpen::Face*>(NXOpen::NXObjectManager::Get(faceTag)); if (face) allFaces.push_back(face); } // 释放面列表内存 if (faceList) UF_MODL_delete_list(&faceList); } // ================ 使用UF函数过滤水平面 ================ std::vector<TaggedObject*> horizontalFaces; const double tolerance = 0.0175; // 约1度(弧度) const double z_axis[3] = { 0.0, 0.0, 1.0 }; // 绝对Z轴方向 for (auto faceObj : allFaces) { tag_t faceTag = faceObj->Tag(); int faceType = 0; // 获取面类型 if (UF_MODL_ask_face_type(faceTag, &faceType) == 0 && faceType == UF_MODL_PLANAR_FACE) { double direction[3] = { 0.0, 0.0, 0.0 }; double point[3] = { 0.0, 0.0, 0.0 }; double box[6] = { 0.0 }; double rad = 0.0; double rad_data[2] = { 0.0 }; int status = 0; // 获取面数据 if (UF_MODL_ask_face_data(faceTag, &faceType, point, direction, box, &rad, rad_data, &status) == 0) { // 计算法向与Z轴的点积 double dot = z_axis[0] * direction[0] + z_axis[1] * direction[1] + z_axis[2] * direction[2]; // 法向平行于Z轴(点积接近1或-1) if (fabs(fabs(dot) - 1.0) < tolerance) { horizontalFaces.push_back(faceObj); } } } } // ================ 结束过滤代码 ================ // ================ 找出Z方向最高的水平面 ================ std::vector<TaggedObject*> highestFaces; double maxZ = -DBL_MAX; // 初始化为最小可能值 // 1. 找出最高Z值 for (auto faceObj : horizontalFaces) { tag_t faceTag = faceObj->Tag(); double box[6]; // [xmin, ymin, zmin, xmax, ymax, zmax] // 获取面的包围盒 if (UF_MODL_ask_bounding_box(faceTag, box) == 0) { // 使用包围盒的zmax作为面的高度 double zMax = box[5]; // 更新最大Z值 if (zMax > maxZ) { maxZ = zMax; } } } // 2. 收集所有位于最高Z值位置的面 const double zTolerance = 0.001; // Z值容差(1毫米) for (auto faceObj : horizontalFaces) { tag_t faceTag = faceObj->Tag(); double box[6]; if (UF_MODL_ask_bounding_box(faceTag, box) == 0) { double zMax = box[5]; // 检查是否在最高Z值位置(考虑容差) if (fabs(zMax - maxZ) < zTolerance) { highestFaces.push_back(faceObj); } } } // ================ 结束最高面选择 ================ // 4. 设置到FaceCollector控件 - 使用最高水平面 face1->SetSelectedObjects(highestFaces); // 5. 刷新界面 UF_DISP_refresh(); //// 显示成功消息 //char msg[256]; //sprintf(msg, "已选择 %d 个最高水平面 (Z = %.2f)", (int)highestFaces.size(), maxZ); //theUI->NXMessageBox()->Show("操作成功", NXMessageBox::DialogTypeInformation, msg); } else { theUI->NXMessageBox()->Show("MICH-明:提示错误", NXMessageBox::DialogTypeError, "面选择控件未初始化!"); } } catch (exception& ex) { theUI->NXMessageBox()->Show("MICH-明:提示异常错误", NXMessageBox::DialogTypeError, ex.what()); } //---------Enter your code here----------- } else if (block == gtbody) { try { // 1. 获取当前显示部件 tag_t displayPart = UF_PART_ask_display_part(); // 获取当前工作部件 if (displayPart == NULL_TAG) // 检查部件是否有效 { theUI->NXMessageBox()->Show("错误提示", NXMessageBox::DialogTypeError, "未找到显示部件!"); return 0; } // 2. 收集所有可见实体 std::vector<tag_t> allBodies; // 存储所有可见实体 tag_t currentBody = NULL_TAG; UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentBody); // 开始遍历实体 while (currentBody != NULL_TAG) // 遍历所有实体 { UF_OBJ_disp_props_t disp_props; if (UF_OBJ_ask_display_properties(currentBody, &disp_props) == 0) // 获取显示属性 { // 仅处理未隐藏实体 if (disp_props.blank_status == UF_OBJ_NOT_BLANKED) // 检查可见性 { int layer_status = 0; UF_LAYER_ask_status(disp_props.layer, &layer_status); // 获取图层状态 // 检查可见图层 if (layer_status == UF_LAYER_WORK_LAYER || layer_status == UF_LAYER_ACTIVE_LAYER || layer_status == UF_LAYER_REFERENCE_LAYER) { allBodies.push_back(currentBody); // 添加到可见实体列表 } } } UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentBody); // 获取下一个实体 } if (allBodies.empty()) // 检查是否有可见实体 { theUI->NXMessageBox()->Show("提示", NXMessageBox::DialogTypeInformation, "部件中没有可见实体!"); return 0; } // 3. 收集需要着色的实体 std::set<tag_t> targetBodies; // 使用set避免重复 const double tolerance = 0.0175; // 约1度(弧度)的法向容差 const double z_axis[3] = { 0.0, 0.0, 1.0 }; // Z轴方向向量 const double z_tolerance = 0.001; // Z坐标容差(1毫米) // 遍历所有实体 for (tag_t bodyTag : allBodies) { uf_list_p_t faceList = NULL; if (UF_MODL_ask_body_faces(bodyTag, &faceList) != 0) continue; // 获取实体所有面 int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); // 获取面数量 double minZ = DBL_MAX; // 初始化最小Z值为最大值 tag_t lowestFace = NULL_TAG; // 存储最低水平面 // 遍历实体的每个面 for (int i = 0; i < faceCount; i++) { tag_t faceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &faceTag); // 获取面标签 int faceType = 0; if (UF_MODL_ask_face_type(faceTag, &faceType) != 0) continue; // 获取面类型 // 只处理平面 if (faceType == UF_MODL_PLANAR_FACE) { double direction[3] = { 0 }; // 面法向 double point[3] = { 0 }; // 面上一点 double box[6] = { 0 }; // 面边界框 double rad = 0, rad_data[2] = { 0 }; int status = 0; // 获取面几何数据 if (UF_MODL_ask_face_data(faceTag, &faceType, point, direction, box, &rad, rad_data, &status) == 0) { // 计算法向与Z轴的点积 double dot = z_axis[0] * direction[0] + z_axis[1] * direction[1] + z_axis[2] * direction[2]; // 检查是否为水平面(法向平行Z轴) if (fabs(fabs(dot) - 1.0) < tolerance) { // 获取面的最低点Z坐标(边界框Zmin) double faceMinZ = box[4]; // 更新最低水平面 if (faceMinZ < minZ) { minZ = faceMinZ; lowestFace = faceTag; } } } } } // 检查是否找到最低水平面且高于XY平面 if (lowestFace != NULL_TAG && minZ > z_tolerance) { targetBodies.insert(bodyTag); // 添加到目标实体集合 } UF_MODL_delete_list(&faceList); // 释放面列表内存 } // 4. 检查是否有符合条件的实体 if (targetBodies.empty()) { theUI->NXMessageBox()->Show("提示", NXMessageBox::DialogTypeInformation, "未找到最低水平面高于XY平面的实体!"); return 0; } // 5. 着色处理 if (color5 != nullptr) // 确保颜色控件有效 { try { // 获取选择的颜色 PropertyList* colorProps = color5->GetProperties(); std::vector<int> colors = colorProps->GetIntegerVector("Value"); int colorID = colors[0]; // 提取颜色ID delete colorProps; // 释放属性对象 // 6. 为实体着色(保留面颜色重置) for (tag_t bodyTag : targetBodies) // 遍历目标实体 { // 重置实体所有面的颜色为继承 uf_list_p_t faceList = NULL; if (UF_MODL_ask_body_faces(bodyTag, &faceList) == 0) { int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); for (int i = 0; i < faceCount; i++) { tag_t faceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &faceTag); UF_OBJ_set_color(faceTag, 0); // 0=继承实体颜色 } UF_MODL_delete_list(&faceList); // 释放面列表 } // 设置实体颜色 UF_OBJ_set_color(bodyTag, colorID); UF_DISP_set_highlight(bodyTag, 0); // 取消高亮 } UF_DISP_refresh(); // 刷新显示 // 显示结果信息 char msg[256]; snprintf(msg, sizeof(msg), "已为 %zu 个实体设置颜色", targetBodies.size()); theUI->NXMessageBox()->Show("着色完成", NXMessageBox::DialogTypeInformation, msg); } catch (std::exception& ex) { theUI->NXMessageBox()->Show("着色错误", NXMessageBox::DialogTypeError, ex.what()); } } else { theUI->NXMessageBox()->Show("错误", NXMessageBox::DialogTypeError, "颜色选择控件未初始化!"); } } catch (std::exception& ex) { theUI->NXMessageBox()->Show("系统错误", NXMessageBox::DialogTypeError, ex.what()); } //---------Enter your code here----------- } else if(block == arcface) { try { if (face1 != nullptr) // 确保面选择控件有效 { // 1. 获取当前显示部件 tag_t displayPart = UF_PART_ask_display_part(); // 获取当前显示的部件标签 if (displayPart == NULL_TAG) // 检查是否获取成功 { theUI->NXMessageBox()->Show("MICH-明:错误提示", NXMessageBox::DialogTypeError, "未找到显示部件!"); // 显示错误信息 return 0; // 提前返回 } // 2. 收集可见实体并筛选最低点高于Z0的实体 std::vector<tag_t> filteredObjects; // 存储符合条件的实体标签 tag_t currentObject = NULL_TAG; // 当前遍历的实体 UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 开始遍历部件中的实体 while (currentObject != NULL_TAG) // 遍历所有实体 { // 检查实体的显示属性 UF_OBJ_disp_props_t disp_props; // 存储显示属性 if (UF_OBJ_ask_display_properties(currentObject, &disp_props) == 0) // 获取显示属性 { // 检查实体是否未被隐藏 if (UF_OBJ_NOT_BLANKED == disp_props.blank_status) // 实体可见 { int layer_status = 0; // 图层状态 if (UF_LAYER_ask_status(disp_props.layer, &layer_status) == 0) // 获取图层状态 { // 检查是否在可见图层上 if (layer_status == UF_LAYER_WORK_LAYER || layer_status == UF_LAYER_ACTIVE_LAYER || layer_status == UF_LAYER_REFERENCE_LAYER) { // 计算实体的边界框 double bbox[6] = { 0 }; // [xmin, ymin, zmin, xmax, ymax, zmax] if (UF_MODL_ask_bounding_box(currentObject, bbox) == 0) // 获取边界框 { // 检查实体最低点是否高于Z0 if (bbox[2] > 0.0) // bbox[2] 是 Zmin { filteredObjects.push_back(currentObject); // 添加到筛选列表 //// 调试信息:显示实体的最低点高度 //char debugMsg[256]; // 调试信息缓冲区 //snprintf(debugMsg, sizeof(debugMsg), // "实体 %d 最低点: %.2f", currentObject, bbox[2]); // 格式化信息 // 使用NXMessageBox替代theUFUI //theUI->NXMessageBox()->Show("调试信息", NXMessageBox::DialogTypeInformation, debugMsg); // 显示调试信息 } } } } } } UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 获取下一个实体 } //// 显示筛选后的实体数量 //char objCountMsg[256]; // 消息缓冲区 //snprintf(objCountMsg, sizeof(objCountMsg), // "找到最低点高于Z0的实体数量: %zu", filteredObjects.size()); // 格式化消息 //theUI->NXMessageBox()->Show("实体筛选", NXMessageBox::DialogTypeInformation, objCountMsg); // 显示消息 if (filteredObjects.empty()) // 检查是否有符合条件的实体 { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeInformation, "没有符合条件的实体!"); // 显示提示 return 0; // 提前返回 } // 3. 从筛选后的实体中收集所有圆弧面 std::vector<NXOpen::TaggedObject*> allFaces; // 存储所有面对象 for (tag_t objectTag : filteredObjects) // 遍历筛选后的实体 { uf_list_p_t faceList = nullptr; // 面列表指针 if (UF_MODL_ask_body_faces(objectTag, &faceList) != 0) continue; // 获取实体所有面 // 自动释放列表内存的RAII封装 auto listDeleter = [](uf_list_p_t* list) { if (*list) UF_MODL_delete_list(list); }; // 自定义删除器 std::unique_ptr<uf_list_p_t, decltype(listDeleter)> listGuard(&faceList, listDeleter); // 智能指针管理 int faceCount = 0; // 面数量 UF_MODL_ask_list_count(faceList, &faceCount); // 获取面数量 for (int i = 0; i < faceCount; i++) // 遍历所有面 { tag_t faceTag = NULL_TAG; // 面标签 UF_MODL_ask_list_item(faceList, i, &faceTag); // 获取面标签 if (auto face = dynamic_cast<NXOpen::Face*>(NXOpen::NXObjectManager::Get(faceTag))) // 转换为面对象 { allFaces.push_back(face); // 添加到面列表 } } } // 4. 收集所有圆弧面(包括圆柱、圆锥和圆角面) std::vector<NXOpen::TaggedObject*> allArcFaces; // 存储圆弧面对象 int cylinderCount = 0, coneCount = 0, blendCount = 0; // 各类面计数器 for (auto faceObj : allFaces) // 遍历所有面 { tag_t faceTag = faceObj->Tag(); // 获取面标签 int faceType = 0; // 面类型 double point[3] = { 0 }; // 点坐标 double dir[3] = { 0 }; // 方向向量 double box[6] = { 0 }; // 边界框 double radius = 0; // 半径 double rad_data[2] = { 0 }; // 半径数据 int norm_dir = 0; // 法线方向 // 获取面数据 if (UF_MODL_ask_face_data(faceTag, &faceType, point, dir, box, &radius, rad_data, &norm_dir) != 0) continue; // 跳过获取失败的面 // 只收集圆弧相关面类型 if (faceType == 16) // 圆柱面 { cylinderCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } else if (faceType == 7) // 圆锥面 { coneCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } else if (faceType == 19) // 圆环曲面 { coneCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } else if (faceType == 18) // 球面 { coneCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } else if (faceType == 23) // 圆角面 { blendCount++; // 增加计数器 allArcFaces.push_back(faceObj); // 添加到圆弧面列表 } } //// 显示圆弧面统计信息 //char debugMsg[256]; // 消息缓冲区 //snprintf(debugMsg, sizeof(debugMsg), // "从筛选实体中找到圆弧面总数: %zu\n圆柱面: %d\n圆锥面: %d\n圆角面: %d", // allArcFaces.size(), cylinderCount, coneCount, blendCount); // 格式化消息 //theUI->NXMessageBox()->Show("圆弧面统计", NXMessageBox::DialogTypeInformation, debugMsg); // 显示消息 if (allArcFaces.empty()) // 检查是否有圆弧面 { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeInformation, "筛选实体中没有圆弧面!"); // 显示提示 return 0; // 提前返回 } // 5. 直接选择所有圆弧面 face1->SetSelectedObjects(allArcFaces); // 设置选中的面 UF_DISP_refresh(); // 刷新显示 //// 显示最终结果 //char msg[256]; // 结果消息缓冲区 //snprintf(msg, sizeof(msg), "已选择 %zu 个圆弧面", allArcFaces.size()); // 格式化消息 //theUI->NXMessageBox()->Show("操作成功", NXMessageBox::DialogTypeInformation, msg); // 显示结果 } } catch (std::exception& ex) // 捕获异常 { theUI->NXMessageBox()->Show("MICH-明:系统错误", NXMessageBox::DialogTypeError, ex.what()); // 显示错误信息 } //---------Enter your code here----------- } else if(block == gaodipoints) { try { // ⚙️ 1. 获取属性列表 PropertyList* colorProps = color11->GetProperties(); // 🎨 2. 获取颜色值:关键属性名为 "Value",返回整数向量 std::vector<int> colors = colorProps->GetIntegerVector("Value"); int colorID = colors[0]; // 取第一个值为颜色索引 delete colorProps;// 🧹 3. 释放属性列表内存(必须!) if (face1 != nullptr) { // 1. 获取显示部件 tag_t displayPart = UF_PART_ask_display_part(); // 获取当前显示部件 if (displayPart == NULL_TAG) // 检查是否获取成功 { theUI->NXMessageBox()->Show("MICH-明:错误提示", NXMessageBox::DialogTypeError, "未找到显示部件!"); return 0; } // 2. 收集可见实体(复用之前代码中的逻辑) std::vector<tag_t> allObjects; tag_t currentObject = NULL_TAG; UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 遍历部件中的实体 while (currentObject != NULL_TAG) { UF_OBJ_disp_props_t disp_props; if (UF_OBJ_ask_display_properties(currentObject, &disp_props) == 0) // 获取显示属性 { if (UF_OBJ_NOT_BLANKED == disp_props.blank_status) // 检查是否消隐 { int layer_status = 0; if (UF_LAYER_ask_status(disp_props.layer, &layer_status) == 0) // 检查图层状态 { if (layer_status == UF_LAYER_WORK_LAYER || layer_status == UF_LAYER_ACTIVE_LAYER || layer_status == UF_LAYER_REFERENCE_LAYER) // 仅处理工作层和参考层 { allObjects.push_back(currentObject); // 添加到可见实体列表 } } } } UF_OBJ_cycle_objs_in_part(displayPart, UF_solid_type, &currentObject); // 继续遍历 } if (allObjects.empty()) // 检查是否有可见实体 { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeInformation, "部件中没有可见实体!"); return 0; } // 3. 准备收集最终选中的面和实体 std::vector<TaggedObject*> resultFaces; // 存储符合条件的面 std::set<tag_t> aboveZ0Bodies; // 存储Z>0的实体(复用之前的逻辑) const double tolerance = 0.0175; // 角度容差(约1度) const double coordTol = 1e-3; // 坐标容差(1微米) const double z_axis[3] = { 0.0, 0.0, 1.0 }; // Z轴方向 // 4. 遍历所有可见实体 for (tag_t bodyTag : allObjects) { // 4.1 收集实体上所有水平面 std::vector<std::pair<tag_t, double>> horizontalFaces; // <面tag, 最小Z坐标> uf_list_p_t faceList = nullptr; if (UF_MODL_ask_body_faces(bodyTag, &faceList) != 0) continue; // 获取实体所有面 // 自动释放列表内存 auto listDeleter = [](uf_list_p_t* list) { if (*list) UF_MODL_delete_list(list); }; std::unique_ptr<uf_list_p_t, decltype(listDeleter)> listGuard(&faceList, listDeleter); int faceCount = 0; UF_MODL_ask_list_count(faceList, &faceCount); // 获取面数量 for (int i = 0; i < faceCount; i++) // 遍历每个面 { tag_t faceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &faceTag); // 获取面tag // 检查是否为水平面 int faceType = 0; if (UF_MODL_ask_face_type(faceTag, &faceType) == 0 && faceType == UF_MODL_PLANAR_FACE) // 只处理平面 { double direction[3] = { 0 }; double point[3] = { 0 }; double box[6] = { 0 }; double rad = 0; double rad_data[2] = { 0 }; int status = 0; if (UF_MODL_ask_face_data(faceTag, &faceType, point, direction, box, &rad, rad_data, &status) == 0) // 获取面数据 { double dot = std::fabs(z_axis[0] * direction[0] + z_axis[1] * direction[1] + z_axis[2] * direction[2]); // 计算法向与Z轴夹角 if (std::abs(dot - 1.0) < tolerance) // 检查是否为水平面 { // 获取面的最小Z坐标 double faceBox[6]; if (UF_MODL_ask_bounding_box(faceTag, faceBox) == 0) // 获取面包围盒 { double minZ = faceBox[2]; // 包围盒Z最小值 horizontalFaces.push_back({ faceTag, minZ }); // 存储水平面信息 } } } } } // 4.2 如果没有水平面则跳过该实体 if (horizontalFaces.empty()) continue; // 4.3 找出除底面外的最低水平面(参考面) // 按Z坐标升序排序 std::sort(horizontalFaces.begin(), horizontalFaces.end(), [](const auto& a, const auto& b) { return a.second < b.second; }); // 按Z值排序 // 找出最低水平面(底面)的高度 double bottomZ = horizontalFaces[0].second; // 找出除底面外的最低水平面高度 double referenceZ = bottomZ; // 初始化为底面高度 bool foundReference = false; for (size_t i = 1; i < horizontalFaces.size(); i++) // 从第二个面开始检查 { // 找到第一个高于底面的水平面 if (horizontalFaces[i].second > bottomZ + coordTol) // 使用容差避免浮点误差 { referenceZ = horizontalFaces[i].second; // 设置参考面高度 foundReference = true; // 标记找到参考面 break; } } // 如果所有水平面都在同一高度(只有底面),则跳过该实体 if (!foundReference) continue; // 4.4 收集实体中高于参考面的所有面 for (int i = 0; i < faceCount; i++) // 再次遍历实体所有面 { tag_t faceTag = NULL_TAG; UF_MODL_ask_list_item(faceList, i, &faceTag); // 获取面tag // 获取面的包围盒 double faceBox[6]; if (UF_MODL_ask_bounding_box(faceTag, faceBox) == 0) // 获取面包围盒 { double minZ = faceBox[2]; // 面的最低点Z坐标 // 面的最低点高于参考面(容差范围内) if (minZ > referenceZ - coordTol) // 使用容差避免浮点误差 { if (auto face = dynamic_cast<NXOpen::Face*>(NXOpen::NXObjectManager::Get(faceTag))) // 转换为Face对象 { resultFaces.push_back(face); // 添加到结果列表 } } } } // 4.5 记录Z>0的实体(复用之前的逻辑) double bodyBox[6]; if (UF_MODL_ask_bounding_box(bodyTag, bodyBox) == 0 && bodyBox[2] > 0.0) // 检查实体是否在Z0以上 { aboveZ0Bodies.insert(bodyTag); // 添加到Z>0实体集合 } } // 5. 检查结果并设置选择 if (resultFaces.empty()) // 检查是否有符合条件的面 { theUI->NXMessageBox()->Show("MICH-明:提示", NXMessageBox::DialogTypeInformation, "未找到符合条件的面!"); return 0; } face1->SetSelectedObjects(resultFaces); // 设置选中的面 for (auto face : resultFaces) { tag_t faceTag = face->Tag(); UF_OBJ_set_color(faceTag, colorID); // 应用颜色 UF_DISP_set_highlight(faceTag, 0); //高亮,0=不高亮,1=高亮 } UF_DISP_refresh(); // 刷新显示 // 6. 显示结果信息 char msg[256]; snprintf(msg, sizeof(msg), "已选中 %zu 个符合条件的面", resultFaces.size()); theUI->NXMessageBox()->Show("操作成功", NXMessageBox::DialogTypeInformation, msg); } } catch (std::exception& ex) // 异常处理 { theUI->NXMessageBox()->Show("MICH-明:系统错误", NXMessageBox::DialogTypeError, ex.what()); } //---------Enter your code here----------- } else if(block == Keyway1) { //---------Enter your code here----------- } } catch(exception& ex) { //---- Enter your exception handling code here ----- gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return 0; } //------------------------------------------------------------------------------ //Callback Name: ok_cb //------------------------------------------------------------------------------ int gaiyansetool::ok_cb() { int errorCode = 0; try { errorCode = apply_cb(); } catch(exception& ex) { //---- Enter your exception handling code here ----- errorCode = 1; gaiyansetool::theUI->NXMessageBox()->Show("Block Styler", NXOpen::NXMessageBox::DialogTypeError, ex.what()); } return errorCode; } //------------------------------------------------------------------------------ //Function Name: GetBlockProperties //Description: Returns the propertylist of the specified BlockID //------------------------------------------------------------------------------ PropertyList* gaiyansetool::GetBlockProperties(const char *blockID) { return theDialog->GetBlockProperties(blockID); }
08-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值