Вопросы по AkelPad Plugin API.

Discuss and announce AkelPad plugins
  • Author
  • Message
Offline
Posts: 84
Joined: Fri May 28, 2010 1:28 pm

Вопросы по AkelPad Plugin API.

Post by private_joker »

Тут будут вопросы по AkelPad Plugin API.
Есть ли способ заменить весь текст в текущем эдит контроле без предварительного выделения с помощью IDM_EDIT_SELECTALL и последующего AKD_REPLACESEL. В принципе у меня работает и так, но я не уверен насчет производительности и необходимости этого выделения.
P.S. Естественно я имею ввиду нативный C/C++ код.

Offline
Posts: 2247
Joined: Tue Aug 07, 2007 2:03 pm
Location: Vinnitsa, Ukraine

Post by FeyFre »

private_joker
Способ номер раз:
EM_SETSEL (0,-1) + EM_REPLACESEL (выделение и замена) непосредственно контролу, а не через главное окно
Способ номер двас(простой как воздух, но незаслуженно забытый):

WM_SETTEXT контролу без никаких предварительных выделений

По вопросам производительности обращайтесь к for и QueryPerformanceCounter и сравнивайте быстродействие сколько Вам угодно.

Offline
Posts: 84
Joined: Fri May 28, 2010 1:28 pm

Post by private_joker »

FeyFre wrote: По вопросам производительности обращайтесь к for и QueryPerformanceCounter и сравнивайте быстродействие сколько Вам угодно.
Вопрос был совсем не об этом.
FeyFre wrote: Способ номер двас(простой как воздух, но незаслуженно забытый):

WM_SETTEXT контролу без никаких предварительных выделений

Этот способ не подходит, т.к. обнуляет буфер отмены. Что как ты (наверное) можешь заметить не является естественным и ожидаемым действием для программы.


FeyFre wrote: Способ номер раз:
EM_SETSEL (0,-1) + EM_REPLACESEL (выделение и замена) непосредственно контролу, а не через главное окно
А вот это посмотрю, благодарю.

Offline
Posts: 876
Joined: Tue Jul 24, 2007 8:54 am

Post by Fr0sT »

У меня вопрос по AKD_GETFRAMEINFO. Я правильно понимаю, что через него можно получить только одно значение зараз? Проглядел сорсы Акеля, вроде бы так и есть. В таком случае получается странновато: какой смысл передавать целую структуру, если возвращается только одно поле, да и то всегда в dwData.
Было бы удобнее, если бы функция на самом деле принимала комбинацию флагов (и заполняла соответствующие поля структуры FRAMEDATA), как это указано в AkelDLL.h

Offline
Site Admin
Posts: 6311
Joined: Thu Jul 06, 2006 7:20 am

Post by Instructor »

Fr0sT
Все элементы структуры итак доступны плагинам через сообщения AKD_FRAME*. Главное назначение AKD_GETFRAMEINFO - использование в скриптах.

Offline
Posts: 876
Joined: Tue Jul 24, 2007 8:54 am

Post by Fr0sT »

Ясно. А получить данные из текущего фрейма можно через
AKD_FRAMEFIND + FWF_CURRENT?

Offline
Posts: 3217
Joined: Wed Nov 29, 2006 1:19 pm
Location: Киев, Русь
Contact:

Post by VladSh »

Fr0sT
Чуток вышло: FileTabs.js.

Offline
Posts: 876
Joined: Tue Jul 24, 2007 8:54 am

Post by Fr0sT »

VladSh
Спасибо! Правда, оказалось, что мне вполне хватит DOCINFO)

Offline
Posts: 876
Joined: Tue Jul 24, 2007 8:54 am

Post by Fr0sT »

Как устроены параметры вызова функций плагина? Смотрел ContextMenu в качестве примера, но из этого

Code: Select all

BOOL IsExtCallParamValid(LPARAM lParam, int nIndex)
{
  if (*((INT_PTR *)lParam) >= (INT_PTR)((nIndex + 1) * sizeof(INT_PTR)))
    return TRUE;
  return FALSE;
}

INT_PTR GetExtCallParam(LPARAM lParam, int nIndex)
{
  if (*((INT_PTR *)lParam) >= (INT_PTR)((nIndex + 1) * sizeof(INT_PTR)))
    return *(((INT_PTR *)lParam) + nIndex);
  return 0;
}
Ни фига не понял.
Ясно, что PLUGINDATA.lParam - это указатель, а вот дальше тёмный лес

DV
Offline
Posts: 1250
Joined: Thu Nov 16, 2006 11:53 am
Location: Kyiv, Ukraine

Post by DV »

Fr0sT wrote:Как устроены параметры вызова функций плагина
Считаем, что lParam - это указатель на массив из элементов INT_PTR (т.е. массив, элементы которого являются INT_PTR). При этом самый первый элемент (с индексом 0) - это количество элементов в массиве, включая и этот самый первый элемент. Например, если передаются три параметра, то значение элемента с индексом 0 равно 3+1=4.
Специфика C такова, что со структурой, состоящей из INT_PTR, можно работать точно так же, как с массивом из того же кол-ва элементов. Т.е.
struct tMyStruct {
INT_PTR size;
INT_PTR i1;
INT_PTR i2;
INT_PTR i3;
} MyStruct;
аналогична
INT_PTR MyArray[4];
При этом нулевой элемент - т.е. size или MyArray[0] в нашем случае должен быть равен 4, указывая на то, что передаются 3 параметра + размер как нулевой параметр.
И lParam = (LPARAM) &MyStruct или же lParam = (LPARAM) MyArray.

Offline
Posts: 876
Joined: Tue Jul 24, 2007 8:54 am

Post by Fr0sT »

DV, ага, ясно. А элементы массива (i1/2/3)? Они сами - указатели на параметры, насколько я понял. А если параметр - число?

DV
Offline
Posts: 1250
Joined: Thu Nov 16, 2006 11:53 am
Location: Kyiv, Ukraine

Post by DV »

Fr0sT,
Пример:

Code: Select all

DWORD dwParam1;
LPCTSTR pszParam2;
int nParam3;

// сами параметры
dwParam1 = 0xFFFFFFFF;
pszParam2 = _T("Abc");
nParam3 = 10;

// передача в структуру
MyStruct.size = 4;
MyStruct.i1 = dwParam1;
MyStruct.i2 = (INT_PTR) pszParam2;
MyStruct.i3 = nParam3;

// передача в массив
MyArray[0] = 4;
MyArray[1] = dwParam1;
MyArray[2] = (INT_PTR) pszParam2;
MyArray[3] = nParam3;
Ну и напоследок: поскольку размер INT_PTR, как и DWORD_PTR, равен размеру указателя (т.е. 4 байта для х86 или 8 байт для х64), а LPCTSTR, в свою очередь, тоже является указателем, можно объявить структуру

Code: Select all

struct tMyStruct2 {
  INT_PTR size;
  DWORD_PTR param1;
  LPCTSTR param2;
  INT_PTR param3;
} MyStruct2;
которая с точки зрения памяти и расположения элементов является идентичной предыдущей tMyStruct. Для этой tMyStruct2 можно задавать параметры dwParam1, pszParam2 и nParam3 без приведения типов - и в то же время её точно так же можно привести к массиву из INT_PTR.

(Добавлено позднее)
В свете вышесказанного можно сослаться на реальный кусок кода из QSearchDlg.c - см. функцию qsearchDoTryUnhighlightAll. В ней используется структура DLLECHIGHLIGHT_UNMARK, объявленная как

Code: Select all

typedef struct sDLLECHIGHLIGHT_UNMARK {
    UINT_PTR dwStructSize;
    INT_PTR nAction;
    UINT_PTR dwMarkID;
} DLLECHIGHLIGHT_UNMARK;
Далее первая же строчка кода убеждает нас в том, что ранее я допустил неточность. Эта строчка

Code: Select all

hlParams.dwStructSize = sizeof(DLLECHIGHLIGHT_UNMARK);
записывает в самый первый (нулевой) параметр не 3 по общему количеству параметров, а размер структуры, равный 3*sizeof(INT_PTR). Ну а дальше - ловкость рук, и никакого мошенства.

Offline
Posts: 2247
Joined: Tue Aug 07, 2007 2:03 pm
Location: Vinnitsa, Ukraine

Post by FeyFre »

Специфика C такова, что со структурой, состоящей из INT_PTR, можно работать точно так же, как с массивом из того же кол-ва элементов.
Вот тут я бы очень даже не согласился. Ибо это очень частный случай, когда на память выделенную "под массив" можно наложить структуру, и все будет хорошо. На практике, дело упирается в обстоятельство именуемое "выравнивание".
"Грузить" могу много, но кратко скажу: АР, а также большинство плагов(мои тоже) работают на честном слове, ибо нигде явно не задается выравнивание полей в торчащих наружу структурах. Выравнивание унаследуется от умолчания компилятора, или от какого-нибудь хидера который об этом подумал, и чудом что у нас соблюдается ABI совместимость.
Так что стоит повнимательнее объявлять структуру накладываемую на lParam, ибо можно промахнуться и в лучшем случае "сделать что-то не то", в хужем - запороть вызывающему стэк или вообще поймать 0xC0000005.

Offline
Posts: 876
Joined: Tue Jul 24, 2007 8:54 am

Post by Fr0sT »

Так... поправьте меня, если ошибаюсь: элементы №1..N могут содержать как указатель на строку, если параметр строковый, так и непосредственно число, если параметр числовой. Способов различить тип данных, хранящихся в ячейке, не существует, поэтому порядок параметров жёстко фиксирован и соблюдается под честное слово (стоит вместо ("bla", 0) передать (0, "bla") - словим AV на null pointer).

Имхо, неплохо было бы это зафиксировать где-то в мануалах, а ещё лучше - завернуть в функции в AkelDLL, выставив наружу только ParamCount и GetParam(idx).

P.S. Пост №666 :)

UPD
Вызываю так (Toolbar):
"" Call("FileInfo::Main", "lala") Icon("%a\AkelFiles\Plugs\FileInfo.dll", 0)

Получаю:
INT_PTR(Pointer(pd.lParam)^) = 8. Wtf?

Offline
Posts: 3217
Joined: Wed Nov 29, 2006 1:19 pm
Location: Киев, Русь
Contact:

Post by VladSh »

Fr0sT
Значит в 0-м параметре надо хранить не только общее количество, но и "массив" идентификаторов типов :)
Post Reply