Scripts discussion (2)

Discuss and announce AkelPad plugins
Locked
  • Author
  • Message
KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

FeyFre
Thank you very much for the information. Please still, tell me how to get following arguments for the function FindResourceEx:
IDS_STRING,
RT_STRING,
langid.

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

Post by FeyFre »

KDJ
RT_STRING is value of resource type identifiers for string resource type, number(WORD 2 bytes only) or \0-terminated string. Equals to 6. You can find its and of other predefined types values in Win32\kernel32.js of mine Win32 Constants Library (you should use it effectively like AkelPad.Include("win32\\kernel32.js"), instead of manual definition if those constants or direct usage of *magic numbers*).

IDS_STRING is resource item identifier, number(WORD) or string(\0 termonated). You must specified value you need to load. Where to obtain it? From the author of module you want to load from. Since you want to load it from AkelPad's language modules, you should get it source(download from Download section here). You need file AkelFiles/Langs/Resources/resource.h there are all resource ID's used in AP and language modules.


I cannot say more. It is number Windows use to identify language. In C code is obtained by using macro MAKELANGID(p,s) ((s<<10)+p).
Where
p - primary language code, like:
LANG_ENGLISH (equals 9) for English,
LANG_RUSSIAN =25
LANG_UKRAINIAN =34
LANG_POLISH =21
etc(list is long - 1024 items)
s - secondary language code. For most of languages valid values for it are only(generic):

Code: Select all

SUBLANG_NEUTRAL =0 (actually it is valid only for LANG_NEUTRAL =0)
SUBLANG_DEFAULT     =1
SUBLANG_SYS_DEFAULT     =2
You should use SUBLANG_DEFAULT for them since it used almost everywhere in resources. MAKELANGID(LANG_RUSSIAN,SUBLANG_DEFAULT)= 1<<10+25= familiar for you 1049 = 0x0419
Some languages are a bit harder to encode, for instance:
LANG_ENGLISH can be:

Code: Select all

SUBLANG_ENGLISH_US   =1 English(USA)
SUBLANG_ENGLISH_UK   =2 English(United Kingdom)
SUBLANG_ENGLISH_AUS  =3 English(Australian)
SUBLANG_ENGLISH_CAN  =4 English(Canadian)
SUBLANG_ENGLISH_NZ   =5 English(New-Zeland)
SUBLANG_ENGLISH_EIRE =6 English(Irish)
... up to
SUBLANG_ENGLISH_PHILIPPINES =13 English(Philippines) 
so MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US) gives 1<<10 +9 = familiar for you 1033 = 0x0409

for LANG_CHINESE =4 you can use

Code: Select all

SUBLANG_CHINESE_TRADITIONAL =1
SUBLANG_CHINESE_SIMPLIFIED  =2
SUBLANG_CHINESE_HONGKONG    =3
SUBLANG_CHINESE_SINGAPORE   =4
SUBLANG_CHINESE_MACAU       =5
so MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED) gives 2<<10 +4 = familiar for you 2052 = 0x0804

If you will use this constants from kernel32.js you must do s + p only, not shifting because it already done in definition(didn't noticed).


This tripe (resource type, resource id, langid) uniquely identifies any resource in resource package(resource archive or image file).

I just realised I mislead you a little. If you going to seek localised version of button on standard AP's dialog, you must load dialog resource using resource type constant RT_DIALOG =5, not string resource, and in returned piece of memory you must parse it as DLGTEMPLATE or DLGTEMPLATEEX structure(see MSDN).

Offline
Posts: 119
Joined: Sat Jan 12, 2008 10:16 am
Location: Shantou, China

Post by cnnnc »

FeyFre and VladSh, Thank you for your criticism.
FeyFre
Zen-coding is a great toolkit for html and css workflow, and it has been renamed and moved to emmet for a while. It seems some update in it. Could you take a little time to update your script with that? :roll:

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

FeyFre
I have a problem with the function FindResourceEx.
In the following script, FindResourceEx returns 0.
What have I done wrong?

Code: Select all

var oSys     = AkelPad.SystemFunction();
var hMainWnd = AkelPad.GetMainWnd();
var nLangID  = AkelPad.GetLangId();
var lpBuffer = AkelPad.MemAlloc(260 * 2); //sizeof(MAX_PATH)
var hLangLib;

if (AkelPad.SendMessage(hMainWnd, 1222 /*AKD_GETMAININFO*/, 52 /*MI_LANGMODULEW*/, lpBuffer))
  hLangLib = oSys.Call("Kernel32::GetModuleHandleW", AkelPad.GetAkelDir(3 /*ADTYPE_LANGS*/) + "\\" + AkelPad.MemRead(lpBuffer, 1 /*DT_UNICODE*/));
else
  //internal language
  hLangLib = AkelPad.GetInstanceExe();

AkelPad.MemFree(lpBuffer);

hRes = oSys.Call("Kernel32::FindResourceExW", hLangLib, 150 /*STR_MESSAGEBOX_CANCEL*/, 6 /*RT_STRING*/, nLangID);
//hRes = oSys.Call("Kernel32::FindResourceExW", hLangLib, 6 /*RT_STRING*/, 150 /*STR_MESSAGEBOX_CANCEL*/, nLangID);

WScript.Echo("hLangLib = " + hLangLib + "\n" +
             "nLangID = " + nLangID + "\n" +
             "hRes = " + hRes);

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

Post by FeyFre »

KDJ
First of all you Resource type argument is second, not third. I.e You should comment 16 line and uncomment 17.
Next, in order to determine error you should use GetLastError function immediately after call:

Code: Select all

hRes = oSys.Call("Kernel32::FindResourceExW", hLangLib, 6 /*RT_STRING*/, 150 /*STR_MESSAGEBOX_CANCEL*/, nLangID);
if(hRes==0)
{
   var lasterror = oSys.GetLastError();
   WScript.Echo(lasterror);
   WScript.Quit();
}
In script you posted here lasterror will be ERROR_RESOURCE_TYPE_NOT_FOUND=1813
(you can obtain human readable error text by calling function FormatMessageW/A)
if you fix 16,17 line you will get good result, or another error(you will get ERROR_RESOURCE_NAME_NOT_FOUND=1814).
And it is not their error. It is peculiarities of FindResourceEx function. It works with raw data stored in resources directory of image(and returns raw data). Don't worry, what I say next not every developer for windows knows, and even I know it accidentally. RT_STRING resources are stored in chunks of string(16 per chunk). That resource ID you use( 150) it threats as Chunk ID, and tries to find it. Fails. So you must convert you string id into chunk id, get raw string chunk, and extract required string manually. I never done that before, but here you can see example(in Russian)
Use ResourceHacker to inspect String resources(you will see strings are chunked)

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

FeyFre
Great thanks. At last I understood how it works.
Below I posted three scripts, which can be used to extract some data from resources.

Code: Select all

var nDlgID = 2004; //IDD_FIND
var sDlgID = nDlgID.toString();

while (true)
{
  sDlgID = AkelPad.InputBox(AkelPad.GetMainWnd(), WScript.ScriptName, "Dialog box ID:", sDlgID);

  if (! sDlgID)
    break;

  nDlgID = parseInt(sDlgID);
  WScript.Echo(GetDialogTitleFromResource(nDlgID));
}

function GetDialogTitleFromResource(nDlgID)
{
  var oSys     = AkelPad.SystemFunction();
  var nLangID  = AkelPad.GetLangId();
  var lpBuffer = AkelPad.MemAlloc(260 * 2); //sizeof(MAX_PATH)
  var sString  = "";
  var hLangLib;

  if (AkelPad.SendMessage(AkelPad.GetMainWnd(), 1222 /*AKD_GETMAININFO*/, 52 /*MI_LANGMODULEW*/, lpBuffer))
    hLangLib = oSys.Call("Kernel32::GetModuleHandleW", AkelPad.GetAkelDir(3 /*ADTYPE_LANGS*/) + "\\" + AkelPad.MemRead(lpBuffer, 1 /*DT_UNICODE*/));
  else //internal language
    hLangLib = AkelPad.GetInstanceExe();

  AkelPad.MemFree(lpBuffer);

  var hRes      = oSys.Call("Kernel32::FindResourceExW", hLangLib, 5 /*RT_DIALOG*/, nDlgID, nLangID);
  var hResData  = oSys.Call("Kernel32::LoadResource", hLangLib, hRes);
  var lpPointer = oSys.Call("Kernel32::LockResource", hResData);
  var nSize     = oSys.Call("Kernel32::SizeofResource", hLangLib, hRes);

  if (nSize)
  {
    //pointer to menu
    if (AkelPad.MemRead(lpPointer + 2, 4 /*DT_WORD*/) == 0xFFFF) //DLGTEMPLATEEX
      lpPointer += 26;
    else //DLGTEMPLATE
      lpPointer += 18;

    //pointer to windowClass
    if (AkelPad.MemRead(lpPointer, 4 /*DT_WORD*/) == 0xFFFF)
      lpPointer += 4;
    else
      lpPointer += AkelPad.MemRead(lpPointer, 1 /*DT_UNICODE*/).length + 2;

    //pointer to title
    if (AkelPad.MemRead(lpPointer, 4 /*DT_WORD*/) == 0xFFFF)
      lpPointer += 4;
    else
      lpPointer += AkelPad.MemRead(lpPointer, 1 /*DT_UNICODE*/).length + 2;

    sString = AkelPad.MemRead(lpPointer, 1 /*DT_UNICODE*/);
  }

  return sString;
}

Code: Select all

var nItemID = 4158; //IDM_EDIT_FIND
var sItemID = nItemID.toString();

while (true)
{
  sItemID = AkelPad.InputBox(AkelPad.GetMainWnd(), WScript.ScriptName, "Menu item ID:", sItemID);

  if (! sItemID)
    break;

  nItemID = parseInt(sItemID);
  WScript.Echo(GetMenuItemFromResource(nItemID));
}

function GetMenuItemFromResource(nItemID)
{
  var oSys     = AkelPad.SystemFunction();
  var nLangID  = AkelPad.GetLangId();
  var lpBuffer = AkelPad.MemAlloc(260 * 2); //sizeof(MAX_PATH)
  var sString  = "";
  var hLangLib;

  if (AkelPad.SendMessage(AkelPad.GetMainWnd(), 1222 /*AKD_GETMAININFO*/, 52 /*MI_LANGMODULEW*/, lpBuffer))
    hLangLib = oSys.Call("Kernel32::GetModuleHandleW", AkelPad.GetAkelDir(3 /*ADTYPE_LANGS*/) + "\\" + AkelPad.MemRead(lpBuffer, 1 /*DT_UNICODE*/));
  else //internal language
    hLangLib = AkelPad.GetInstanceExe();

  AkelPad.MemFree(lpBuffer);

  var hRes      = oSys.Call("Kernel32::FindResourceExW", hLangLib, 4 /*RT_MENU*/, 4001 /*IDM_MENU_MAIN*/, nLangID);
  var hResData  = oSys.Call("Kernel32::LoadResource", hLangLib, hRes);
  var lpPointer = oSys.Call("Kernel32::LockResource", hResData);
  var nSize     = oSys.Call("Kernel32::SizeofResource", hLangLib, hRes);

  if (nSize)
  {
    var nPos = AkelPad.MemRead(lpPointer, 1 /*DT_UNICODE*/, nSize / 2).indexOf("\0" + String.fromCharCode(nItemID));

    if (nPos >= 0)
      sString = AkelPad.MemRead(lpPointer + (nPos + 2) * 2, 1 /*DT_UNICODE*/);
  }

  return sString;
}

Code: Select all

var nStrID = 150; //STR_MESSAGEBOX_CANCEL
var sStrID = nStrID.toString();

while (true)
{
  sStrID = AkelPad.InputBox(AkelPad.GetMainWnd(), WScript.ScriptName, "Resource string ID:", sStrID);

  if (! sStrID)
    break;

  nStrID = parseInt(sStrID);
  WScript.Echo(GetStringFromResource(nStrID));
}

function GetStringFromResource(nStrID)
{
  var oSys      = AkelPad.SystemFunction();
  var nLangID   = AkelPad.GetLangId();
  var lpBuffer  = AkelPad.MemAlloc(260 * 2); //sizeof(MAX_PATH)
  var nStrTabID = Math.floor(nStrID / 16) + 1; //string table ID
  var nStrInTab = nStrID % 16;
  var sString   = "";
  var hLangLib;

  if (AkelPad.SendMessage(AkelPad.GetMainWnd(), 1222 /*AKD_GETMAININFO*/, 52 /*MI_LANGMODULEW*/, lpBuffer))
    hLangLib = oSys.Call("Kernel32::GetModuleHandleW", AkelPad.GetAkelDir(3 /*ADTYPE_LANGS*/) + "\\" + AkelPad.MemRead(lpBuffer, 1 /*DT_UNICODE*/));
  else //internal language
    hLangLib = AkelPad.GetInstanceExe();

  AkelPad.MemFree(lpBuffer);

  var hRes      = oSys.Call("Kernel32::FindResourceExW", hLangLib, 6 /*RT_STRING*/, nStrTabID, nLangID);
  var hResData  = oSys.Call("Kernel32::LoadResource", hLangLib, hRes);
  var lpPointer = oSys.Call("Kernel32::LockResource", hResData);
  var nSize     = oSys.Call("Kernel32::SizeofResource", hLangLib, hRes);

  if (nSize)
  {
    for (var i = 0; i < nStrInTab; ++i)
      lpPointer += (AkelPad.MemRead(lpPointer, 4 /*DT_WORD*/) + 1) * 2;

    nSize   = AkelPad.MemRead(lpPointer, 4 /*DT_WORD*/);
    sString = AkelPad.MemRead(lpPointer + 2, 1 /*DT_UNICODE*/, nSize);
  }

  return sString;
}
Last edited by KDJ on Wed Jan 02, 2013 5:46 pm, edited 1 time in total.

Offline
Posts: 119
Joined: Sat Jan 12, 2008 10:16 am
Location: Shantou, China

Post by cnnnc »

KDJ wrote:GetStringFromResource.js

Code: Select all

  nStrID = AkelPad.InputBox(AkelPad.GetMainWnd(), WScript.ScriptName, "Resource string ID:", nStrID);

  if (! nStrID)
It's not correct.
Below is corrected:

Code: Select all

  sStrID = AkelPad.InputBox(AkelPad.GetMainWnd(), WScript.ScriptName, "Resource string ID:", sStrID);

  if (! sStrID)

Offline
Posts: 767
Joined: Mon Sep 28, 2009 10:03 am
Location: Minsk, Belarus

Post by se7h »

cnnnc wrote:FeyFre
Zen-coding is a great toolkit for html and css workflow, and it has been renamed and moved to emmet for a while. It seems some update in it. Could you take a little time to update your script with that? :roll:
+1

Offline
Posts: 176
Joined: Sat Dec 24, 2011 4:05 pm

Post by F. Phoenix »

KDJ, I finished translation of your FindFiles.js, but has 2 moments, which modified:
  • Need about +10px for better translation of "Don't search in larger than:" label
  • " B " for "bytes" in status bar was untranslatable

Code: Select all

sTxtScriptName  = "Поиск файлов";
sTxtDir         = "&Каталог";
sTxtCurrent     = "&Текущий";
sTxtBrowse      = "&Выбрать...";
sTxtSubDirs     = "Подкаталоги &уровень:";
sTxtAll         = "Все";
sTxtFileName    = "&Имя файла";
sTxtWildcards   = "(поддерживаются шаблоны: *?)";
sTxtRegExp      = "Регулярные выражения";
sTxtTextInFile  = "&Текст в файле";
sTxtNotName     = "Кроме этих имён";
sTxtMatchCase   = "С учетом регистра";
sTxtMultiline   = "Многострочно";
sTxtNotContain  = "Не содержащие текст";
sTxtInStreams   = "Включить NTFS потоки";
sTxtSkipBinary  = "Не искать в бинарных";
sTxtSkipLarger  = "Не искать, если крупнее:";
sTxtFiles       = "Файлы";
sTxtSearch      = "Искать";
sTxtEdit        = "Правка";
sTxtCopyList    = "Копировать";
sTxtClearList   = "Очистить";
sTxtSettings    = "Настройки";
sTxtClose       = "Закрыть";
sTxtChooseDir   = "Выберите каталог:";
sTxtNoFiles     = "<нет файлов>";
sTxtSeparateWnd = "Запустить в отдельном окне";
sTxtKeepFiles   = "Вывод списка файлов";
sTxtPathShow    = "Показать полный путь в списке файлов";
sTxtDirNoExist  = "Каталог не существует.";
sTxtFileNoExist = "Файлы не существуют.";
sTxtErrorRE     = "Ошибка в регулярном выражении.";
sTxtNTFSStream  = "Поток NTFS";
sTxtWait        = "Подождите...";
sHlpAnyChar     = "любой одиночный символ";
sHlpAnyString   = "любая подстрока";
sHlpSemicolQuot = "точка с запятой (если внутри кавычек)";
sHlpListSepar   = "разделитель списка имен (вне кавычек)";
sHlpAnyChar_NL  = "любой символ, кроме \\n";
sHlpDigit       = "цифра [0-9]";
sHlpNonDigit    = "не цифра [^0-9]";
sHlpWhiteSp     = "пробельный символ [ \\f\\n\\r\\t\\v]";
sHlpNonWhiteSp  = "непробельный символ";
sHlpWordChar    = "словесный символ [A-Za-z0-9_]";
sHlpNonWordChar = "несловесный символ";
sHlpNULL        = "нулевой символ";
sHlpFF          = "перевод страницы \\x0C";
sHlpNL          = "перевод строки \\x0A";
sHlpCR          = "возврат каретки \\x0D";
sHlpTab         = "табуляция \\x09";
sHlpVTab        = "вертикальная табуляция \\x0B";
sHlpCharHex     = "символ с кодом FF";
sHlpUniCharHex  = "символ юникода 00FF";
sHlpBegin       = "начало строки или текста";
sHlpEnd         = "конец строки или текста";
sHlpWordBoun    = "граница слова";
sHlpNonWordBoun = "не граница слова";
sHlpAlternative = "одна из альтнатив: ab либо xy";
sHlpCharSet     = "набор символов, нужен любой из них";
sHlpNegCharSet  = "исключающий набор символов";
sHlpRange       = "диапазон символов от a до z";
sHlpNegRange    = "исключающий диапазон";
sHlpCapture     = "запоминающая скобка";
sHlpNotCapture  = "незапоминающая скобка";
sHlpFollow      = "далее следует ab";
sHlpNotFollow   = "далее не следует ab";
sHlpBackrefer   = "обратная ссылка";
sHlpZeroOrOne   = "0 или 1 раз";
sHlpZeroOrMore  = "0 или более раз";
sHlpOneOrMore   = "1 или более раз";
sHlpexactly     = "ровно 3 раза";
sHlpAtLeast     = "не менее 3 раз";
sHlpFromTo      = "от 3 до 7 раз";
sHlpSpecChars   = "()[]{}^$.?+*|\\ специальные символы";


Code: Select all

@@ -789 +789 @@ function ResizeWindow(hWnd)
-            75,
+            85,
@@ -796 +796 @@ function ResizeWindow(hWnd)
-            75,
+            85,
@@ -1090 +1090 @@ function SetTextSB(nItem)
-      sText1 = "\t\t" + AkelPad.MemRead(lpBuffer, DT_UNICODE) + " B ";
+      sText1 = "\t\t" + AkelPad.MemRead(lpBuffer, DT_UNICODE) + sTxtByte;
@@ -1763,0 +1764 @@ function ReadIni()
+    sTxtByte        = " B ";


Both versions: FindFiles-Rus.7z
Last edited by F. Phoenix on Wed Jan 02, 2013 5:53 pm, edited 1 time in total.

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

cnnnc wrote:...
It's not correct.
...
Oh yes. Fixed.

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

F. Phoenix
Thank you for the translation.
And can you use a shorter alternative of "Не искать в файлах крупнее:"?
Eg: "Не искать в больших, чем:" or "Не искать в крупнее, чем:".
Similarly as: "Не искать в бинарных".

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

Post by DV »

KDJ wrote:And can you use a shorter alternative of "Не искать в файлах крупнее:"?
"Не искать в файлах >" :)

Offline
Posts: 176
Joined: Sat Dec 24, 2011 4:05 pm

Post by F. Phoenix »

KDJ, in this case I prefere "Не искать в больших, чем:", but don't see the problem to increase it. And what about add bytes mark after input field? For something like this: screenshot.

DV, вот там из-за отстутствия этой "Б", по моему, как раз и есть основной недостаток интуитивности. Тем более, что поле ввода текстовое, а не NumericUpDown. А с ней вполне неплохо бы воспринималось и "Не искать в больших, чем:", и твое "Не искать в файлах >"; а так этот символ еще, к примеру, в виде стрелки частенько юзается.

Offline
Posts: 366
Joined: Mon Jan 10, 2011 5:28 pm
Contact:

Post by Lenchik »

А настолько ли большая проблема делать эти окошки и шрифты не пиксельных размеров, а растягивающимися под размеры шрифтов пользователя? Вот я увеличил шрифты в системе. Opera и utorrent на это отреагировали отлично - всё растянулось и всё читабельно. А Акельпад неоднозначно среагировал - в меню шрифт изменился и менюшки подвинулись, но статусная строка под ширину надписей не исправилась и кое-что съедается, в настройках и заголовках вкладок mdi шрифт не сменился (и, соответственно, смотрится мелко на фоне остальных программ). Плагины и скрипты так и остались на прописанных в них шрифтах и размерах. Могут ли разработчики учитывать то, что пользоатель может хотеть все смотерть большим шрифтом или не тем, который за него впишет разработчик?

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

Post by DV »

Lenchik wrote:Могут ли разработчики учитывать то, что пользоатель может хотеть все смотерть большим шрифтом или не тем, который за него впишет разработчик?
Вообще - да. Просто дело в том, что реализация этого дела средствами Win API сделана, выражаясь словами одного из наших политиков, "немножко по-дебильному". Часто просто неохота возиться со всеми этими контекстами устройств, шрифтами и прочим отстоем ради пересчёта размеров.
Locked