Выбор ключевого слова и Нижняя черта (_)

Автор Тема: Выбор ключевого слова и Нижняя черта (_)  (Прочитано 21978 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Вот собственно код:
Код - C# [Выбрать]
  1.     [Rtm.CommandMethod("GetAttib")]    
  2.     static public void GetAttrib()
  3.     {
  4.         App.Document acDoc = App.Application.DocumentManager.MdiActiveDocument;
  5.         Db.Database acCurDb = acDoc.Database;
  6.         Ed.Editor acEd = acDoc.Editor;
  7.  
  8.         Ed.PromptKeywordOptions KeyOpt = new Ed.PromptKeywordOptions("\n Выбранный блок содержит следующие атрибуты:");
  9.         KeyOpt.AllowNone = true;
  10.         //KeyOpt.AllowArbitraryInput = true;
  11.         KeyOpt.AppendKeywordsToMessage = true;
  12.  
  13.         KeyOpt.Keywords.Add("ОТМЕТКА");
  14.         KeyOpt.Keywords.Add("ВТОРАЯ_СТРОКА");
  15.         KeyOpt.Keywords.Default = "ОТМЕТКА";
  16.  
  17.         Ed.PromptResult KeyRes = acEd.GetKeywords(KeyOpt);
  18.         if (KeyRes.Status != Ed.PromptStatus.OK)
  19.         {
  20.             acEd.WriteMessage("\n Отмена выбора атрибута.");
  21.             return;
  22.         }
  23.         acEd.WriteMessage("\n Выбран атрибут: " + KeyRes.StringResult);
  24.     }

Вот результат его выполнения:


Собственно вопрос: как сделать что бы все работало корректно?

Если "ВТОРАЯ_СТРОКА" заменить на "ВТОРАЯСТРОКА", то все работает отлично, однако такое решение мне не нравится.
Я понимаю, что вопрос наверное ламерский и ответ где-то на поверхности, но уже часа 4 его не могу найти. Заранее спасибо.
« Последнее редактирование: 30-04-2014, 16:00:34 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Символ подчеркивания (она же "Нижняя черта") является разделителем между локальным и глобальным именем. Например, "Да_Yes" позволяет вводить ключевое слово и как Да, и как Yes. Так что использовать символ подчеркивания в составе ключевого слова ты не можешь. Можешь попробовать не GetKeywords, а GetString.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн bargool

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
А если попробовать вот так? :
Код - C# [Выбрать]
  1. PromptKeywordOptions("\n Выбранный блок содержит следующие атрибуты: [ОТМЕТКА / ВТОРАЯ_СТРОКА]", "ОТМЕТКА СТРОКА");
только тогда KeyRes.StringResult будет "СТРОКА" для второй_строки, хотя не уверен, что вообще сработает
Алексей

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
GetString
Не получается =(
Валится на 15 строчке.
Код - C# [Выбрать]
  1.     [Rtm.CommandMethod("GetAttib")]    
  2.     static public void GetAttrib()
  3.     {
  4.         App.Document acDoc = App.Application.DocumentManager.MdiActiveDocument;
  5.         Db.Database acCurDb = acDoc.Database;
  6.         Ed.Editor acEd = acDoc.Editor;
  7.  
  8.         Ed.PromptStringOptions KeyOpt = new Ed.PromptStringOptions("\n Выбранный блок содержит следующие атрибуты:");
  9.         KeyOpt.AllowSpaces = true;
  10.         KeyOpt.AppendKeywordsToMessage = true;
  11.         KeyOpt.Keywords.Add("ОТМЕТКА");
  12.         KeyOpt.Keywords.Add("ВТОРАЯ_СТРОКА");
  13.         KeyOpt.Keywords.Default = "ОТМЕТКА";
  14.  
  15.         Ed.PromptResult KeyRes = acEd.GetString(KeyOpt);
  16.         if (KeyRes.Status != Ed.PromptStatus.OK)
  17.         {
  18.             acEd.WriteMessage("\n Отмена выбора атрибута.");
  19.             return;
  20.         }
  21.         acEd.WriteMessage("\n Выбран атрибут: " + KeyRes.StringResult);
  22.     }


Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Не получается =(
Валится на 14 строчке.
А я что-то говорил том, что тут нужно использовать ключевые слова ( т.е. KeyOpt.Keywords.Add("..."); ) ?
1. Убери все KeyOpt.Keywords.Add
2. Попробуй:
Код - C# [Выбрать]
  1. Ed.PromptStringOptions KeyOpt =
  2.   new Ed.PromptStringOptions("\n Выбранный блок содержит следующие атрибуты [ОТМЕТКА/ВТОРАЯ_ОТМЕТКА]: ");
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Цитировать
Command: NETLOAD
Command: GETATTIB
 Выбранный блок содержит следующие атрибуты [ОТМЕТКА/ВТОРАЯ_ОТМЕТКА]: ВТОРАЯ
 Выбран атрибут: ВТОРАЯ
Command: GETATTIB
 Выбранный блок содержит следующие атрибуты [ОТМЕТКА/ВТОРАЯ_ОТМЕТКА]: ОТМЕТКА
 Выбран атрибут: ОТМЕТКА
Command: GETATTIB
 Выбранный блок содержит следующие атрибуты [ОТМЕТКА/ВТОРАЯ_ОТМЕТКА]: ВТОРАЯ
 Выбран атрибут: ВТОРАЯ

Видимо придется как то обруливать эту ситуацию, т.к. делалось все это для тегов атрибутов и там эта нижняя черта сплошь и рядом.  :(

Оффлайн bargool

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Видимо придется как то обруливать эту ситуацию, т.к. делалось все это для тегов атрибутов и там эта нижняя черта сплошь и рядом.  :(
Для атрибутов вообще плохо ключевые слова использовать. Если у пользователя отключён динамический ввод (или как его там, когда опции списком рядом с курсором появляются), то выбор нужного варианта будет геморройным (написать полностью придётся).
Уж лучше маленькое окошко рисовать, со списком.
Алексей

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Видимо придется как то обруливать эту ситуацию, т.к. делалось все это для тегов атрибутов и там эта нижняя черта сплошь и рядом.  :(
Нужно выбирать атрибут по имени или в него можно ткнуть? Если можно ткнуть, то всё намного проще, а если нельзя, то в общем случае наверное нужно сделать свою форму со списком имен атрибутов и оттуда выбирать.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Т.к. штатный qselect не позволяет отсеивать блоки по значению атрибута в блоке, то хотелось следующего:
1. Тыкнуть в блок
2. Получить список атрибутов в блоке и тыкнуть на нужном
3. Получить список возможных значений выбранного атрибута и тыкнуть в нужный
4. Подсветить, выделить, обозначить нужные блоки.

Все написал, и стал тестировать... попался блок с атрибутом содержащем  _ и тут понеслось =(

наверное нужно сделать свою форму со списком имен атрибутов и оттуда выбирать
Так и сделал. Работает.

ЗЫ. Добавлю видео:

« Последнее редактирование: 06-05-2014, 09:09:18 от Boxa.Shu »

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Славно! Пользователи должны оценить.
От себя добавлю, что диалоговые методы "выбрать один элемент из списка" (WinForm, ListBox) и "выбрать несколько элементов из списка" (WinForm, CheckedListBox) у меня уже давно поселились во вспомогательной библиотеке и уже много раз я не пожалел об этом :)

Оффлайн Константин Соков

  • ADN Club
  • **
  • Сообщений: 56
  • Карма: 0
Boxa.Shu, может выложишь исходник с чертежем, так сказать поучиться уму разуму :)?

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Так и сделал. Работает.
Неплохо. А ежели в модели отметок с одинаковыми значениями наберётся пару десятков (отображается в разных Layout), тогда как? :)

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Константин Соков, мне не жалко выложить, но стыдно. Корявость и криворукость в коде напрягают даже меня. Рефакторинг сделаю пару раз и выложу.

Андрей Бушман, Намекаешь на предварительный выбор? Нет, он не обрабатывается, ищутся все вхождения выбранного блока только в пространстве модели. Блок отметок использовал для проверки выбора измененных динамических блоков и как будет работать dll с тегами атрибутов содержащих "_".

Основная цель преследуемая при написании этой dll, это поиск блоков. Найти занумерованное отверстие, пояс. Что там с ним дальше делать, дело десятое. Главное найти.

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
стыдно. Корявость и криворукость в коде напрягают даже меня.
Этот критерий бесконечен в течении времени - не парьтесь.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Порой рефакторинг может привести даже к тому, что код и вовсе перестаёт работать. :)

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Ну я предупреждал...
И да, я знаю что перебирать все объекты в модели это дурной тон, с наскоку получить вхождения блоков из таблицы не получилось, какой то затык с измененными дин блоками (пример работы смотрел тут http://adn-cis.org/kak-najti-vse-vstavki-dinamicheskogo-bloka.html , но видимо не разобрался до конца). Позже этот фрагмент программы перепишу адаптирую.
Да и использование переменных класса без сетеров и геторов "не айс"...

update. (2014-05-12)
При редактирование исправил код основного модуля:
 - добавил предварительный выбор
 - добавил фильтр при переборе объектов в модели.

Код - C# [Выбрать]
  1. // Основной модуль
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Windows.Forms;
  6.  
  7. using App = Autodesk.AutoCAD.ApplicationServices;
  8. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  9. using Db = Autodesk.AutoCAD.DatabaseServices;
  10. using Ed = Autodesk.AutoCAD.EditorInput;
  11. using Gem = Autodesk.AutoCAD.Geometry;
  12. using Rtm = Autodesk.AutoCAD.Runtime;
  13. using Gi = Autodesk.AutoCAD.GraphicsInterface;
  14.  
  15. namespace QuickSelect
  16. {
  17.     public class Commands
  18.     {
  19.         public static List<string> AttList = new List<string>();
  20.         public static string AttValue = "";
  21.         private static string Exit = "Exit";
  22.  
  23.         static public void ClearAttListValue()
  24.         {
  25.             AttValue = "";
  26.             AttList.Clear();
  27.             AttList.Add(Exit);
  28.         }
  29.  
  30.  
  31.         [Rtm.CommandMethod("bx_quickselect", Rtm.CommandFlags.UsePickSet  |
  32.                                              Rtm.CommandFlags.Redraw |
  33.                                              Rtm.CommandFlags.Modal)]
  34.         static public void bx_quickselect()
  35.         {
  36.             // Получение текущего документа и базы данных
  37.             App.Document acDoc = App.Application.DocumentManager.MdiActiveDocument;
  38.             Db.Database acCurDb = acDoc.Database;
  39.             Ed.Editor acEd = acDoc.Editor;
  40.             ClearAttListValue();
  41.  
  42.             //Секция предварительного выбора
  43.             Ed.PromptSelectionResult acSSPrompt = acEd.SelectImplied();
  44.             Ed.SelectionSet acSSet = null;
  45.  
  46.             // Если статус запроса OK, объекты были выбраны перед запуском команды
  47.             if (acSSPrompt.Status == Ed.PromptStatus.OK)
  48.                             acSSet = acSSPrompt.Value;
  49.  
  50.             Dictionary<Db.ObjectId, string> ObjID_Dic = new Dictionary<Db.ObjectId, string>();
  51.  
  52.             Ed.PromptEntityOptions EntOpt = new Ed.PromptEntityOptions("\n Select block:");
  53.             EntOpt.SetRejectMessage("\n Entity must be a block.");
  54.             EntOpt.AddAllowedClass(typeof(Db.BlockReference), false);
  55.             EntOpt.AllowObjectOnLockedLayer = true;
  56.             Ed.PromptEntityResult EntRes = acEd.GetEntity(EntOpt);
  57.  
  58.             if (EntRes.Status != Ed.PromptStatus.OK)
  59.             {
  60.                 acEd.WriteMessage("\n Cencel.");
  61.                 return;
  62.             }
  63.  
  64.             String acBlockName = "0";
  65.  
  66.             // старт транзакции
  67.             // Ищу истенное имя выбранного блока и читаю его атрибуты
  68.             using (Db.Transaction acTrans = acCurDb.TransactionManager.StartOpenCloseTransaction())
  69.             {
  70.                 // Открытие таблицы Блоков для чтения
  71.                 Db.BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
  72.                                                 Db.OpenMode.ForRead) as Db.BlockTable;
  73.                 // Открытие записи таблицы Блоков пространства Модели для записи
  74.                 Db.BlockTableRecord acBlkTblRecMS = acTrans.GetObject(acBlkTbl[Db.BlockTableRecord.ModelSpace],
  75.                                                 Db.OpenMode.ForRead) as Db.BlockTableRecord;
  76.                
  77.                 //Получаю выбранный блок
  78.                 Db.BlockReference acBlock = acTrans.GetObject(EntRes.ObjectId, Db.OpenMode.ForRead) as Db.BlockReference;
  79.                 //Получаю определение блока в таблице блоков
  80.                 Db.BlockTableRecord acBlkTblRec = acTrans.GetObject(acBlock.BlockTableRecord, Db.OpenMode.ForRead)
  81.                     as Db.BlockTableRecord;
  82.      
  83.  
  84.                 // Получаю определение блока в таблице динамических блоков
  85.                 // Запоминаю истинное имя блока
  86.                 acBlockName = acBlock.Name;
  87.  
  88.                 if (acBlock.IsDynamicBlock)
  89.                 {
  90.                     acBlkTblRec = acTrans.GetObject(acBlock.DynamicBlockTableRecord, Db.OpenMode.ForRead) as Db.BlockTableRecord;
  91.                     Db.BlockTableRecord blr_nam = acTrans.GetObject(acBlkTblRec.ObjectId, Db.OpenMode.ForRead) as Db.BlockTableRecord;
  92.                     acBlockName = blr_nam.Name;
  93.                 }
  94.  
  95.                 if (acBlkTblRec.HasAttributeDefinitions)
  96.                 {
  97.                     foreach (Db.ObjectId objID in acBlkTblRec)
  98.                     {
  99.                         Db.DBObject dbObj = acTrans.GetObject(objID, Db.OpenMode.ForRead) as Db.DBObject;
  100.                         if (dbObj is Db.AttributeDefinition)
  101.                         {
  102.                             Db.AttributeDefinition acAtt = dbObj as Db.AttributeDefinition;
  103.                             if (AttList.Contains(acAtt.Tag) != true)
  104.                                 AttList.Add(acAtt.Tag);
  105.                         }
  106.                     }
  107.                 }
  108.                 //Я в этой транзакции ничего не меняю, Все открываю только для чтения.
  109.                 //соответственно и вносить изменения не нужно.
  110.                 //acTrans.Commit();
  111.             }
  112.  
  113.  
  114.             if (AttList.Count == 1)
  115.                 return;
  116.  
  117.             QuickSelect.Form1 myform_name = new QuickSelect.Form1();
  118.             Autodesk.AutoCAD.ApplicationServices.Application.ShowModalDialog(myform_name);
  119.  
  120.             if (AttValue == Exit)
  121.                 return;
  122.  
  123.             string AttName = AttValue;
  124.             // Вот тут нужно очистить переменные
  125.             ClearAttListValue();
  126.             //// тут получить все возможние значения данного атрибута и
  127.             //// заполним массив AttList снова вызвать форму
  128.             using (Db.Transaction acTrans = acCurDb.TransactionManager.StartOpenCloseTransaction())
  129.             {
  130.                 if (acSSet == null)
  131.                 {
  132.                     Db.TypedValue[] acTypValAr = new Db.TypedValue[1];
  133.                     Db.TypedValue typedValue = new Db.TypedValue(0, "INSERT");
  134.                     acTypValAr.SetValue(typedValue, 0);
  135.                     Ed.SelectionFilter acSelFtr = new Ed.SelectionFilter(acTypValAr);
  136.                     acSSPrompt = acEd.SelectAll(acSelFtr);
  137.                     acSSet = acSSPrompt.Value;
  138.                 }
  139.  
  140.                 foreach (Db.ObjectId objID in acSSet.GetObjectIds())
  141.                 {
  142.                     // Проверка, нужно убедится в правильности полученного объекта
  143.                     if (objID != null)
  144.                     {
  145.                         // Открытие объекта для
  146.                         Db.Entity dbObj = acTrans.GetObject(objID, Db.OpenMode.ForRead) as Db.Entity;
  147.                         if (dbObj != null)
  148.                         {
  149.                             if (dbObj is Db.BlockReference)
  150.                             {
  151.                                 Db.BlockReference acBlock = dbObj as Db.BlockReference;
  152.                                 Db.BlockTableRecord acBlkTblRec;
  153.                                 acBlkTblRec = acTrans.GetObject(acBlock.BlockTableRecord, Db.OpenMode.ForRead) as Db.BlockTableRecord;
  154.  
  155.                                 String BlockName = acBlock.Name;
  156.                                 if (acBlock.IsDynamicBlock)
  157.                                 {
  158.                                     acBlkTblRec = acTrans.GetObject(acBlock.DynamicBlockTableRecord, Db.OpenMode.ForRead) as Db.BlockTableRecord;
  159.                                     Db.BlockTableRecord blr_nam = acTrans.GetObject(acBlkTblRec.ObjectId, Db.OpenMode.ForRead) as Db.BlockTableRecord;
  160.                                     BlockName = blr_nam.Name;
  161.                                 }
  162.  
  163.                                 if (BlockName == acBlockName)
  164.                                 {
  165.                                     if (acBlkTblRec.HasAttributeDefinitions)
  166.                                     {
  167.                                         foreach (Db.ObjectId objID_In_Block in acBlock.AttributeCollection)
  168.                                         {
  169.                                             Db.DBObject dbObj_In_Block = acTrans.GetObject(objID_In_Block, Db.OpenMode.ForRead) as Db.DBObject;
  170.                                             if (dbObj_In_Block is Db.AttributeReference)
  171.                                             {
  172.                                                 Db.AttributeReference acAtt = dbObj_In_Block as Db.AttributeReference;
  173.                                                 if (acAtt.Tag == AttName)
  174.                                                 {
  175.                                                     ObjID_Dic.Add(acBlock.ObjectId, acAtt.TextString);
  176.  
  177.                                                     if (AttList.Contains(acAtt.TextString) == false)
  178.                                                         AttList.Add(acAtt.TextString);
  179.                                                 }
  180.                                             }
  181.                                         }
  182.                                     }
  183.                                 }
  184.                             }
  185.                         }
  186.                     }
  187.                 }
  188.                 //Я в этой транзакции ничего не меняю, Все открываю только для чтения.
  189.                 //соответственно и вносить изменения не нужно.
  190.                 //acTrans.Commit();
  191.             }
  192.  
  193.            //Выводим форму для выбора значения
  194.             QuickSelect.Form1 myform_value = new QuickSelect.Form1();
  195.             Autodesk.AutoCAD.ApplicationServices.Application.ShowModalDialog(myform_value);
  196.  
  197.             if (AttValue == Exit)
  198.                 return;
  199.             // Добавляем в набор выбираемых объекты удовлетворяющие условию
  200.             IEnumerable<Db.ObjectId> L = from KeyValuePair<Db.ObjectId, string> q in ObjID_Dic
  201.                                          where q.Value.ToString() == AttValue.ToString()
  202.                                          select q.Key;
  203.             //Подсвечиваем объекты
  204.             Db.ObjectId[] idarrayEmpty = L.ToArray();
  205.             acEd.SetImpliedSelection(idarrayEmpty);
  206.         }
  207.     }
  208. }

Код - C# [Выбрать]
  1. // Форма
  2. using System;
  3. using System.Windows.Forms;
  4. namespace QuickSelect
  5. {
  6.     public partial class Form1 : Form
  7.     {
  8.         public Form1()
  9.         {
  10.             InitializeComponent();
  11.         }
  12.         private void Form1_Load(object sender, EventArgs e)
  13.         {
  14.             foreach(string str in QuickSelect.Commands.AttList)
  15.             {
  16.                 listBox1.Items.Add(str);
  17.             }
  18.         }
  19.  
  20.         private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
  21.         {
  22.             try
  23.             {
  24.                 QuickSelect.Commands.AttValue = listBox1.SelectedItem.ToString();
  25.                 this.Close();
  26.             }
  27.             catch (Exception)
  28.             {
  29.                
  30.                 //throw;
  31.             }
  32.         }
  33.     }
  34. }
  35.  
« Последнее редактирование: 12-05-2014, 17:02:42 от Boxa.Shu »

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Код - C# [Выбрать]
  1. listBox1.Items.AddRange(QuickSelect.Commands.AttList);
и тогда можно, наверное, обойтись без BeginUpdate и EndUpdate.

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Код - C# [Выбрать]
  1. listBox1.Items.AddRange(QuickSelect.Commands.AttList);
и тогда можно, наверное, обойтись без BeginUpdate и EndUpdate.
Угу, можно. Проверил и поправил код.