How to read the font size from AkelPad.ini file?

English main discussion
Post Reply
  • Author
  • Message
KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

How to read the font size from AkelPad.ini file?

Post by KDJ »

Hi, I have this problem.
AkelPad.ini contains an entry:
Font=F1FFFFFF000000000000000000000000900100000000000003020131
How to interpret this?
How to read font size (in point), style and others?
I mean the general principle.

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

Post by FeyFre »

KDJ, in general case you will be not able to decode values in this option, because in easy to understand form they available only on graphics layer(i.e in Win GDI).

Read this article LOGFONT and you will understand whole thing(this option is actually dumped LOGFONT structure without last field lfFaceName, which have separate option in AkelPad).

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

Post by Instructor »

KDJ
AKD_GETFONTW?

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

Post by FeyFre »

Instructor
Думаю KDJ всё-таки желал разобраться как оно представляется в настроечном файле(значении реестра), а не через скрипты. Врочем одно-другому не мешает. :)

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

Post by KDJ »

FeyFre, Instructor
Gentlemen, thank you very much for your help.
I'm trying to read the font size in the script.

Code: Select all

var hMainWnd = AkelPad.GetMainWnd();
var oSys = AkelPad.SystemFunction();
var hDC  = oSys.Call("user32::GetDC", hMainWnd);
var nDevCap = oSys.Call("gdi32::GetDeviceCaps" , hDC, 90 /*LOGPIXELSY*/);
var nFontSize = oSys.Call("kernel32::MulDiv", 0xF1FFFFFF, 72, nDevCap);
The result is nFontSize = -176160769.
In fact, the font size is 11 pt.
I do not understand this.

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

Post by Instructor »

You were close :)

Code: Select all

var hMainWnd=AkelPad.GetMainWnd();
var hWndEdit=AkelPad.GetEditWnd();
var oSys=AkelPad.SystemFunction();

WScript.Echo("" + GetFontPoint(hWndEdit));

function GetFontPoint(hWndEdit)
{
  var lpLogFont;
  var lfHeight;
  var hDC;
  var nDevCap;
  var nPointSize=0;

  if (lpLogFont=AkelPad.MemAlloc(92 /*sizeof(LOGFONTW)*/))
  {
    AkelPad.SendMessage(hMainWnd, 1233 /*AKD_GETFONTW*/, hWndEdit, lpLogFont);
    lfHeight=AkelPad.MemRead(lpLogFont + 0 /*offsetof(LOGFONTW, lfHeight)*/, 3 /*DT_DWORD*/);

    if (hDC=oSys.Call("user32::GetDC", hWndEdit))
    {
      nDevCap=oSys.Call("gdi32::GetDeviceCaps", hDC, 90 /*LOGPIXELSY*/);
      nPointSize=-oSys.Call("kernel32::MulDiv", lfHeight, 72, nDevCap);
      oSys.Call("user32::ReleaseDC", hWndEdit, hDC);
    }
    AkelPad.MemFree(lpLogFont);
  }
  return nPointSize;
}

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

Post by KDJ »

Thanks Instructor.
I suppose I understand.
In AklePad.ini file, the bytes are in reverse order. And lfHeight is negative.
Instead 0xF1FFFFFF, I should write 0xFFFFFFF1.

Code: Select all

var nFontSize = -oSys.Call("kernel32::MulDiv", 0xFFFFFFF1, 72, nDevCap);

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

Post by KDJ »

I wrote the script FontIniSize.js, which sets the initial font size from AkelPad.ini file.
I was unable to load the font settings using the functions AKD_INIOPEN and AKD_INIGETVALUE. Problem solved otherwise.
The following code generates this error: type mismatch.

Code: Select all

var hMainWnd = AkelPad.GetMainWnd();
var pIniFile = AkelPad.GetAkelDir() + "\\AkelPad.ini";
var hIniFile = AkelPad.SendMessage(hMainWnd, 1366 /*AKD_INIOPEN*/, 0x1 /*POB_READ*/, pIniFile);

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

Post by FeyFre »

KDJ
But you also should check if AkelPad stores settings in Registry.
(If, as you said, RegRead does not reads Binary values, you can use native API to read data from registry: advapi32::RegOpenKeyEx advapi32::RegQueryValueEx advapi32::RegCloseKey, etc see MSDN)

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

Post by KDJ »

FeyFre, thank you for the information.
I tried to read data from the registry (REG_BINARY type) using the method ActiveXObject("WScript.Shell").RegRead().
But the return value is "VBArray of integers".
JavaScript does not recognize this value (type=unknown).
Probably should write the script in VBS.
I will try to still do it in JS using Advapi32::RegQueryValueEx.

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

Post by KDJ »

Unfortunately, I failed to read the registry value "HKLM\Software\ Akelsoft\AkelPad\Options\Font" in JS.
I tried these features:
oSys.Call("Advapi32.dll::RegOpenKeyExW", HKEY_CURRENT_USER, "Software\\Akelsoft\\AkelPad\\Options", 0, KEY_QUERY_VALUE, lphKey);
oSys.Call("Advapi32.dll::RegQueryValueExW", hKey, "Font", 0, lpType, lpData, lpSize);
and
oSys.Call("Advapi32.dll::RegOpenCurrentUser", KEY_QUERY_VALUE, lphKey);
oSys.Call("Advapi32.dll::RegGetValueW", hKey, "Software\\Akelsoft\\AkelPad\\Options", "Font", 0x0000FFFF, lpType, lpData, lpSize);

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

Post by FeyFre »

KDJ
Probably you missed something.

Code: Select all

function MakeString(str)
{
	var res = AkelPad.MemAlloc((str.length+1)*_TSIZE);
	AkelPad.MemCopy(res, str, _TSTR);
	return res;
}
var HKCU = 0x80000001;
var KEY_QUERY_VALUE = 0x0001;
var DT_DWORD = 3;
var REG_BINARY = 3;
var ERROR_SUCCES = 0;
var ERROR_MORE_DATA = 234;

var SubKey = MakeString("SOFTWARE\\Akelsoft\\AkelPad\\Options");
var Value = MakeString("Font");
var LPKEY = AkelPad.MemAlloc(4);

var result = AkelPad.SystemFunction().Call("advapi32::RegOpenKeyEx"+_TCHAR,
			HKCU,					//! Parent key
			SubKey,					//! Subkey
			0,						//! Reserved. must be 0
			KEY_QUERY_VALUE,		//! Desired access
			LPKEY);					//! Result key
if(result == ERROR_SUCCES)
{
	var KEY = AkelPad.MemRead(LPKEY, DT_DWORD);
	var LPTYPE = AkelPad.MemAlloc(4);
		AkelPad.MemCopy(LPTYPE, REG_BINARY, DT_DWORD); //! I prefer to init this value
	var LPDATASIZE = AkelPad.MemAlloc(4);
		AkelPad.MemCopy(LPDATASIZE, 28, DT_DWORD);
	var BUFFER = AkelPad.MemAlloc(28);
	result = AkelPad.SystemFunction().Call("advapi32::RegQueryValueEx"+_TCHAR,
			KEY,		//! Parent key
			Value,		//! Value name
			0,			//! Must be NULL
			LPTYPE,		//! Value type receiver: will be REG_BINARY
			BUFFER,		//! Buffer
			LPDATASIZE);//! Buffer size
	if(	(result == ERROR_SUCCES || result == ERROR_MORE_DATA) &&
		(AkelPad.MemRead(LPTYPE, DT_DWORD)==REG_BINARY)&&	//! Must be binary
		(AkelPad.MemRead(LPDATASIZE, DT_DWORD)>=4)			//! Must be at least 4 bytes
		)
	{
		var lfHeight  =  AkelPad.MemRead(BUFFER,DT_DWORD);
		var hDC       =  AkelPad.SystemFunction().Call("user32::GetDC", AkelPad.GetMainWnd()); 
		var nDevCap   =  AkelPad.SystemFunction().Call("gdi32::GetDeviceCaps" , hDC, 90 /*LOGPIXELSY*/); 
		var nFontSize = -AkelPad.SystemFunction().Call("kernel32::MulDiv", lfHeight, 72, nDevCap); 
		AkelPad.SystemFunction().Call("user32::ReleaseDC", AkelPad.GetMainWnd(), hDC);
		AkelPad.MessageBox(0, "Size is: "+nFontSize, "Caption", 0);
	}
	AkelPad.SystemFunction().Call("advapi32::RegCloseKey",KEY);
	AkelPad.MemFree(BUFFER);
	AkelPad.MemFree(LPDATASIZE);
	AkelPad.MemFree(LPTYPE);
}
AkelPad.MemFree(LPKEY);
AkelPad.MemFree(Value);
AkelPad.MemFree(SubKey);

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

Post by KDJ »

FeyFre, thanks.
Actually, I made a few mistakes.
I still have a few questions:
Why do you allocate memory at a string of one byte more?
Why do you initiate LPTYPE value?
Why DATASIZE must be at least 4 bytes?

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

Post by FeyFre »

Why do you allocate memory at a string of one byte more?
First of all, not one byte bigger, byte one char bigger(1 byte for ANSI, 2 bytes for Unicode).
Because WINAPI works with so called Zero-terminated strings - arrays of chars which last element is zero(if you forget put zero there all functions will continue process string until they meet it).
Why do you initiate LPTYPE value?
It is my personal habit. In most cases I use functions which require pointers to initialized memory and I used to do such initializations whenever presence or absence such requirements.
Why DATASIZE must be at least 4 bytes?
Validation. Because I read 4 bytes from buffer later. In case when this options is broken(manually edited by nasty user) I will be sure I will not try to use invalid data.

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

Post by KDJ »

For now I solved the problem of reading from the registry in VBS -> FontIniSize.vbs
Later I'll try to do it in JS. According to the lesson from FeyFre.
Post Reply