[CDR X4 и ранее] Добавить кнопку на панель свойств

fersat

Участник
Топикстартер
Сообщения
15
Реакции
11
У панели свойств есть несколько режимов отображения (modes) и у каждого режима свой набор контролов. Я могу добавить кнопку в режим по умолчанию, но добраться до остальных режимов не получается.

Этот код возвращает ошибку 445 "Object doesn't support this action" (Несмотря на то, что я могу просмотреть объект Modes через Watch в VBA IDE)
Код:
Application.CommandBars.Item("Property Bar").Modes.Item("Несколько объектов")

Я нашёл ID нужного режима - "4568875c-712c-438e-93bb-024a436e52ca", можно как нибудь получить интерфейс ICUICommandBarMode по этому ID?
 

dastin

Некромант-любитель
12 лет на форуме
Сообщения
2 147
Реакции
2 053
Последнее редактирование:

dastin

Некромант-любитель
12 лет на форуме
Сообщения
2 147
Реакции
2 053
вот некоторые подробности ...

!!!! из Х5 !!!!
т.е не факт что они будут работать в Х4

которого просто нет


<container modeID="4568875c-712c-438e-93bb-024a436e52ca"> режим Properties bar при выделении 2+ объектов
<item guidRef="a41164ff-c9e9-4b2c-954a-095f4204538e" /> position
<item guidRef="325d7c86-da3a-4610-bd25-5cf98cf66a41" />size
<item guidRef="266435b4-6e53-460f-9fa7-f45be187d400" />separator
<item guidRef="42bef211-16e5-4b4f-b9ee-52b7b5476232" />scale
<item guidRef="d289f32b-3808-4510-b892-fd2cb0820209" />proportional ratio
<item guidRef="266435b4-6e53-460f-9fa7-f45be187d400" />separator
<item guidRef="8723ad52-3e31-473c-8756-7ae85abcc483" />angle
<item guidRef="266435b4-6e53-460f-9fa7-f45be187d400" />separator
<item guidRef="e6644135-9dab-4935-8ab9-fc85527810ca" />mirror horizont
<item guidRef="6ae897fd-2eab-4dad-b172-f4fb768c273e" />mirror vert
<item guidRef="266435b4-6e53-460f-9fa7-f45be187d400" />separator
<item guidRef="91774a85-4ed5-4eb5-9ba4-cb9190253446" />combine
<item guidRef="266435b4-6e53-460f-9fa7-f45be187d400" />separator
<item guidRef="5e4f94a0-302a-473a-9f73-94b55f1ba689" />group
<item guidRef="76aa0c75-bfb7-4b85-ade0-2b938157c515" />ungroup
<item guidRef="4a31123e-06f1-4ba1-993c-391a5f50830f" />ungroup all
<item guidRef="266435b4-6e53-460f-9fa7-f45be187d400" />separator
<item guidRef="416c9d7d-7ca2-4947-92b7-7c4b8191ca2c" />weld
<item guidRef="1d425d4a-4ca9-4130-87ae-78eae87ead13" />trim
<item guidRef="e5b41ae3-8c3b-4c5e-9f0f-46b4e5f1d9d0" />intersect
<item guidRef="7da36c72-627c-4782-b51a-01718a43551b" />simplify
<item guidRef="49d4605c-e1fd-4574-83f9-6bb8e57bf93a" />front minus back
<item guidRef="f64b0582-0028-47dc-a075-f29a0a65fcba" />back minus front
<item guidRef="b0491566-5ffe-450a-b17e-f2f496b4eb22" />boundary
<item guidRef="266435b4-6e53-460f-9fa7-f45be187d400" />separator
<item guidRef="7109900f-4789-4451-9ba7-bb3df86db569" />align and distribute

ЗЫ - separatop - разделитель - вертикальная палочка между кнопками

так какую кнопку вы хотите добавить?
 
Последнее редактирование:

fersat

Участник
Топикстартер
Сообщения
15
Реакции
11

Вложения

  • 1.png
    1.png
    29.9 КБ · Просм.: 46

dastin

Некромант-любитель
12 лет на форуме
Сообщения
2 147
Реакции
2 053
Ну например вот
ну вот ID кнопок я вам развернул ...
Вы хотите какую-то из них задействовать?
Или воткнуть свою (на которую повешен макрос), чтобы она показывалась только в этом режиме?
 

fersat

Участник
Топикстартер
Сообщения
15
Реакции
11
Я хочу добавить свою кнопку, чтобы она отображалась в двух режимах - "несколько объектов" и "кривая". На кнопке будет не макрос а команда плагина (тип кнопки cdrCmdCategoryPlugins), то есть при нажатии будет выполняться IVGAppPlugin.Invoke. Я знаю что это можно сделать через "UserUI.xslt" (читал это - Creating Ruler Tool for CorelDRAW or Corel DESIGNER - Docs & Tutorials - Developer Area - CorelDRAW Community), но хочу обойтись одним cpg файлом.
 
  • Спасибо
Реакции: dastin

fersat

Участник
Топикстартер
Сообщения
15
Реакции
11
В общем метод ICUICommandBarModes.Get_Item не реализован (возвращает E_NOTIMPL), но судя по всему до него можно добраться через invoke.

Есть такое описание интерфейса
Код:
ICUICommandBarModesDisp = dispinterface
    ['{9CEE0005-42A0-5980-43A3-7AA71461482C}']
    property Item[IndexOrName: OleVariant]: ICUICommandBarMode readonly dispid 0; default;
    property Count: Integer readonly dispid 1610743809;
    property _NewEnum: IUnknown readonly dispid -4;
  end;
Использовать этот диспинтерфейс как есть не получилось - похоже в Delphi 7 нельзя использовать OleVariant в качестве параметра для метода dispinterface.

Пробую вручную вызвать invoke с dispid=0 (это dispid метода Get_Item).
Код:
var
   curv: WideString='кривая';
  _par: tagVARIANT=(vt: VT_BSTR;pbstrVal:@curv);
  res: tagVARIANT;
  param: dispparams=(rgvarg: @_par;cArgs: 1);

...

CorelApp.CommandBars.Item['Property Bar'].Modes.Invoke(0,IID_NULL,0,DISPATCH_PROPERTYGET,param,@res,0,0);
И получаю DISP_E_EXCEPTION. Видимо я неправильно заполняю структуру dispparams. Нужно разбираться дальше.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 228
Реакции
10 851
OMFG, а вы этим всем управлять через дельфи собрались, да еще и винтажной версии??? 'shok2'
 

fersat

Участник
Топикстартер
Сообщения
15
Реакции
11
Delphi 7 использую только для отладки (наиболее быстро и удобно для меня).

Итак я заглянул в структуру EXCEPTINFO, которую возвращает Invoke и там тоже E_NOTIMPL. Но до интерфейса ICUICommandBarMode я таки добрался. Вот proof of concept (этот код выводит имена всех режимов панели свойств)
Код:
{$APPTYPE CONSOLE}
uses
  Windows,VGCore_TLB,ActiveX;

type
  IEnumVariant = interface(IUnknown)
    ['{00020404-0000-0000-C000-000000000046}']
    function Next(celt: LongWord; var rgvar: tagVariant; out pceltFetched: LongWord): HResult; stdcall;
    function Skip(celt: LongWord): HResult; stdcall;
    function Reset: HResult; stdcall;
    function Clone(out Enum: IEnumVariant): HResult; stdcall;
  end;

var
  CorelCLSID: TGUID;
  CorelApp:   IVGApplication;
  mode:       ICUICommandBarMode;
  fetched:    Cardinal;
  enum:       IEnumVariant;
  res:        tagVariant;
  Controls:   ICUIControls;

begin
  SetConsoleOutputCP(1251);
  CoInitialize(0);
  CLSIDFromProgID('CorelDRAW.Application',CorelCLSID);
  CoCreateInstance(CorelCLSID,nil,CLSCTX_LOCAL_SERVER,IVGApplication,CorelApp);
  CorelApp.CommandBars.Item['Property Bar'].Modes._NewEnum.QueryInterface(IEnumVariant,enum);
  enum.Reset;
  while enum.Next(1,res,fetched)=S_OK do
  begin
    IUnknown(res.dispVal).QueryInterface(ICUICommandBarMode,mode);
    controls:=mode.Controls; //Метод завершается с кодом S_OK, но в controls всегда 0
    writeln(mode.Name);
  end;
  readln;
end.
К сожалению метод Get_Controls всегда возвращает 0, хотя и завершается без ошибок. Так что кнопку таким способом не добавить.
 

Вложения

  • 1.png
    1.png
    10.1 КБ · Просм.: 25

fersat

Участник
Топикстартер
Сообщения
15
Реакции
11
Любопытный факт: если перевести панель свойств в нужный режим, то Application.CommandBars("Property Bar") вернёт интерфейс для этого режима. Так что в принципе можно повесить обработчик на событие изменения выделения, затем по ID первого контрола панели определить текущий режим и если это нужный режим и кнопка не добавлена - добавить её.
 

fersat

Участник
Топикстартер
Сообщения
15
Реакции
11
Во вложении пример реализации CPG. Плагин добавляет кнопку на все режимы панели свойств, у которых есть кнопки "Объединить" или "Разъединить". При нажатии на кнопку выдаётся MessageBox. Для установки скопировать cpg в каталог Draw\Plugins (если такого нет - создать). Работает в CorelDraw X3 и выше (32-битные версии).
 

Вложения

  • CPG Example.7z
    113.8 КБ · Просм.: 19