Вопросы по AkelPad Plugin API.
- Author
- Message
-
Offline
- Posts: 84
- Joined: Fri May 28, 2010 1:28 pm
Вопросы по AkelPad Plugin API.
Тут будут вопросы по AkelPad Plugin API.
Есть ли способ заменить весь текст в текущем эдит контроле без предварительного выделения с помощью IDM_EDIT_SELECTALL и последующего AKD_REPLACESEL. В принципе у меня работает и так, но я не уверен насчет производительности и необходимости этого выделения.
P.S. Естественно я имею ввиду нативный C/C++ код.
Есть ли способ заменить весь текст в текущем эдит контроле без предварительного выделения с помощью IDM_EDIT_SELECTALL и последующего AKD_REPLACESEL. В принципе у меня работает и так, но я не уверен насчет производительности и необходимости этого выделения.
P.S. Естественно я имею ввиду нативный C/C++ код.
-
Offline
- Posts: 2247
- Joined: Tue Aug 07, 2007 2:03 pm
- Location: Vinnitsa, Ukraine
private_joker
Способ номер раз:
EM_SETSEL (0,-1) + EM_REPLACESEL (выделение и замена) непосредственно контролу, а не через главное окно
Способ номер двас(простой как воздух, но незаслуженно забытый):
WM_SETTEXT контролу без никаких предварительных выделений
По вопросам производительности обращайтесь к for и QueryPerformanceCounter и сравнивайте быстродействие сколько Вам угодно.
Способ номер раз:
EM_SETSEL (0,-1) + EM_REPLACESEL (выделение и замена) непосредственно контролу, а не через главное окно
Способ номер двас(простой как воздух, но незаслуженно забытый):
WM_SETTEXT контролу без никаких предварительных выделений
По вопросам производительности обращайтесь к for и QueryPerformanceCounter и сравнивайте быстродействие сколько Вам угодно.
-
Offline
- Posts: 84
- Joined: Fri May 28, 2010 1:28 pm
Вопрос был совсем не об этом.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
У меня вопрос по AKD_GETFRAMEINFO. Я правильно понимаю, что через него можно получить только одно значение зараз? Проглядел сорсы Акеля, вроде бы так и есть. В таком случае получается странновато: какой смысл передавать целую структуру, если возвращается только одно поле, да и то всегда в dwData.
Было бы удобнее, если бы функция на самом деле принимала комбинацию флагов (и заполняла соответствующие поля структуры FRAMEDATA), как это указано в AkelDLL.h
Было бы удобнее, если бы функция на самом деле принимала комбинацию флагов (и заполняла соответствующие поля структуры FRAMEDATA), как это указано в AkelDLL.h
-
Offline
- Posts: 3217
- Joined: Wed Nov 29, 2006 1:19 pm
- Location: Киев, Русь
- Contact:
Fr0sT
Чуток вышло: FileTabs.js.
Чуток вышло: FileTabs.js.
-
Offline
- Posts: 876
- Joined: Tue Jul 24, 2007 8:54 am
Как устроены параметры вызова функций плагина? Смотрел ContextMenu в качестве примера, но из этого
Ни фига не понял.
Ясно, что PLUGINDATA.lParam - это указатель, а вот дальше тёмный лес
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 - это указатель, а вот дальше тёмный лес
-
Offline
- Posts: 1250
- Joined: Thu Nov 16, 2006 11:53 am
- Location: Kyiv, Ukraine
Считаем, что lParam - это указатель на массив из элементов INT_PTR (т.е. массив, элементы которого являются INT_PTR). При этом самый первый элемент (с индексом 0) - это количество элементов в массиве, включая и этот самый первый элемент. Например, если передаются три параметра, то значение элемента с индексом 0 равно 3+1=4.Fr0sT wrote:Как устроены параметры вызова функций плагина
Специфика 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: 1250
- Joined: Thu Nov 16, 2006 11:53 am
- Location: Kyiv, Ukraine
Fr0sT,
Пример:
Ну и напоследок: поскольку размер INT_PTR, как и DWORD_PTR, равен размеру указателя (т.е. 4 байта для х86 или 8 байт для х64), а LPCTSTR, в свою очередь, тоже является указателем, можно объявить структуру
которая с точки зрения памяти и расположения элементов является идентичной предыдущей tMyStruct. Для этой tMyStruct2 можно задавать параметры dwParam1, pszParam2 и nParam3 без приведения типов - и в то же время её точно так же можно привести к массиву из INT_PTR.
(Добавлено позднее)
В свете вышесказанного можно сослаться на реальный кусок кода из QSearchDlg.c - см. функцию qsearchDoTryUnhighlightAll. В ней используется структура DLLECHIGHLIGHT_UNMARK, объявленная как
Далее первая же строчка кода убеждает нас в том, что ранее я допустил неточность. Эта строчка
записывает в самый первый (нулевой) параметр не 3 по общему количеству параметров, а размер структуры, равный 3*sizeof(INT_PTR). Ну а дальше - ловкость рук, и никакого мошенства.
Пример:
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;
Code: Select all
struct tMyStruct2 {
INT_PTR size;
DWORD_PTR param1;
LPCTSTR param2;
INT_PTR param3;
} MyStruct2;
(Добавлено позднее)
В свете вышесказанного можно сослаться на реальный кусок кода из 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);
-
Offline
- Posts: 2247
- Joined: Tue Aug 07, 2007 2:03 pm
- Location: Vinnitsa, Ukraine
Вот тут я бы очень даже не согласился. Ибо это очень частный случай, когда на память выделенную "под массив" можно наложить структуру, и все будет хорошо. На практике, дело упирается в обстоятельство именуемое "выравнивание".Специфика C такова, что со структурой, состоящей из INT_PTR, можно работать точно так же, как с массивом из того же кол-ва элементов.
"Грузить" могу много, но кратко скажу: АР, а также большинство плагов(мои тоже) работают на честном слове, ибо нигде явно не задается выравнивание полей в торчащих наружу структурах. Выравнивание унаследуется от умолчания компилятора, или от какого-нибудь хидера который об этом подумал, и чудом что у нас соблюдается ABI совместимость.
Так что стоит повнимательнее объявлять структуру накладываемую на lParam, ибо можно промахнуться и в лучшем случае "сделать что-то не то", в хужем - запороть вызывающему стэк или вообще поймать 0xC0000005.
-
Offline
- Posts: 876
- Joined: Tue Jul 24, 2007 8:54 am
Так... поправьте меня, если ошибаюсь: элементы №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?
Имхо, неплохо было бы это зафиксировать где-то в мануалах, а ещё лучше - завернуть в функции в 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: