Scripts discussion (1)

Discuss and announce AkelPad plugins
Locked
  • Author
  • Message
Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

Чем нам грозит что-то вроде

Code: Select all

var hWndDialog = oSys.Call("user32::FindWindowEx" + _TCHAR, 0, 0, dialogClass, 0);
if(hWndDialog) {
	oSys.Call("user32::ShowWindow", hWndDialog, 9 /*SW_RESTORE*/);
	AkelPad.SendMessage(hWndDialog, 7 /*WM_SETFOCUS*/, 0, 0);
	return;
}

if(
	!AkelPad.WindowRegisterClass(dialogClass)
	&& ( // Previous script instance crashed
		!AkelPad.WindowUnregisterClass(dialogClass)
		|| !AkelPad.WindowRegisterClass(dialogClass)
	)
)
	return;
?
А то надоело перезапускать AkelPad после возникновения ошибки в скрипте. :)
То есть мы проверяем, что окна нет, но класс все еще зарегистрирован. И пробуем снять регистрацию.

P.S. Кстати, скриптам из комплекта плагина тоже хорошо бы восстанавливать свернутое диалоговое окно.

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

Post by Instructor »

Infocatcher wrote:И как вообще положено проверять, попадет ли окно в рабочую область?
См. EnsureWindowInMonitor в файле исходников Edit.c.
Infocatcher wrote:P.S. Кстати, скриптам из комплекта плагина тоже хорошо бы восстанавливать свернутое диалоговое окно.
Добавил.

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

Instructor wrote:См. EnsureWindowInMonitor в файле исходников Edit.c.
Как-то очень хитро.
Я правильно понимаю, что GetWindowRect() для нескольких мониторов возвращает большие координаты (для второго и далее мониторов), так что достаточно просто их сохранить, а при восстановлении сделать проверку?

Странно. Вроде бы есть смысл восстанавливать положение любого окна (за редкими исключениями в виде каких-нибудь диалогов уровня Да/Нет/Отмена) – это удобно, а в WinAPI нету простого механизма для этого.

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

Infocatcher wrote:
Instructor wrote:См. EnsureWindowInMonitor в файле исходников Edit.c.
Как-то очень хитро.
А почему не
hMonitor = MonitorFromRect(lpRect, MONITOR_DEFAULTTONEAREST)
=> GetMonitorInfoA(hMonitor, LPMONITORINFO lpMi)
=> rcMonitor, rcWork
+ коррекция, чтобы влезало в rcWork
?

А вот как предполагается получать основной (primary) монитор, я не понял.
Вот что должно вернуть*

Code: Select all

MonitorFromRect(lpRect, MONITOR_DEFAULTTOPRIMARY)
, если область не находится ни в одном мониторе?

[Upd]
Для экспериментов:

Code: Select all

var oSys = AkelPad.SystemFunction();

var dlgX = 9999;
var dlgY = 9999;

restoreWindowPosition(AkelPad.GetMainWnd());

function restoreWindowPosition(hWnd, hWndParent) {
	//if(dlgX == undefined || dlgY == undefined) {
	//	centerWindow(hWnd, hWndParent);
	//	return;
	//}

	var rcWnd = getWindowRect(hWnd);
	if(!rcWnd)
		return;

	var lpRect = AkelPad.MemAlloc(16); //sizeof(RECT)
	if(!lpRect)
		return;
	AkelPad.MemCopy(lpRect,      dlgX,                              3 /*DT_DWORD*/);
	AkelPad.MemCopy(lpRect + 4,  dlgY,                              3 /*DT_DWORD*/);
	AkelPad.MemCopy(lpRect + 8,  dlgX + (rcWnd.right - rcWnd.left), 3 /*DT_DWORD*/);
	AkelPad.MemCopy(lpRect + 12, dlgY + (rcWnd.top - rcWnd.bottom), 3 /*DT_DWORD*/);
	var hMonitor = oSys.Call("user32::MonitorFromRect", lpRect, 0x2 /*MONITOR_DEFAULTTONEAREST*/);
	//var hPrimaryMonitor = oSys.Call("user32::MonitorFromRect", lpRect, 0x1 /*MONITOR_DEFAULTTOPRIMARY*/);

	if(hMonitor) {
		//typedef struct tagMONITORINFO {
		//  DWORD cbSize;
		//  RECT  rcMonitor;
		//  RECT  rcWork;
		//  DWORD dwFlags;
		//} MONITORINFO, *LPMONITORINFO;
		var sizeofMonitorInfo = 4 + 16 + 16 + 4;
		var lpMi = AkelPad.MemAlloc(sizeofMonitorInfo);
		if(lpMi) {
			AkelPad.MemCopy(lpMi, sizeofMonitorInfo, 3 /*DT_DWORD*/);
			oSys.Call("user32::GetMonitorInfo" + _TCHAR, hMonitor, lpMi);
			var rcWork = parseRect(lpMi + 4 + 16);
			AkelPad.MemFree(lpMi);
		}
	}
	else { //?
		oSys.Call("user32::SystemParametersInfo" + _TCHAR, 48 /*SPI_GETWORKAREA*/, 0, lpRect, 0);
		var rcWork = parseRect(lpRect);
	}
	AkelPad.MemFree(lpRect);

	if(rcWork) {
		var edge = Math.max(
			16,
			oSys.Call("user32::GetSystemMetrics", 8 /*SM_CYFIXEDFRAME*/)
				+ oSys.Call("user32::GetSystemMetrics", 4 /*SM_CYCAPTION*/)
		);

		var minX = rcWork.left - (rcWnd.right - rcWnd.left) + edge;
		var minY = rcWork.top;
		var maxX = rcWork.right - edge;
		var maxY = rcWork.bottom - edge;

		dlgX = Math.max(minX, Math.min(maxX, dlgX));
		dlgY = Math.max(minY, Math.min(maxY, dlgY));
	}

	oSys.Call("user32::SetWindowPos", hWnd, 0, dlgX, dlgY, 0, 0, 0x15 /*SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE*/);
}
function getWindowRect(hWnd, hWndParent) {
	var lpRect = AkelPad.MemAlloc(16); //sizeof(RECT)
	if(!lpRect)
		return null;
	oSys.Call("user32::GetWindowRect", hWnd, lpRect);
	hWndParent && oSys.Call("user32::ScreenToClient", hWndParent, lpRect);
	var rcWnd = parseRect(lpRect);
	AkelPad.MemFree(lpRect);
	return rcWnd;
}
function parseRect(lpRect) {
	return {
		left:   AkelPad.MemRead(lpRect,      3 /*DT_DWORD*/),
		top:    AkelPad.MemRead(lpRect +  4, 3 /*DT_DWORD*/),
		right:  AkelPad.MemRead(lpRect +  8, 3 /*DT_DWORD*/),
		bottom: AkelPad.MemRead(lpRect + 12, 3 /*DT_DWORD*/)
	};
}

Есть счастливые обладатели двух мониторов?

[Upd – 2]
Включил второй экран. Разумеется, ничего на нем не видно, но, вроде бы, работает. :)

[Upd – 3]
*А, понял, это я неправильно доку прочитал.


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

Post by Instructor »

Кто-то интересовался насчет индикатора выполнения скрипта. Пример по использованию можно посмотреть здесь: LinesWrap.js.
Last edited by Instructor on Thu Apr 21, 2011 4:03 pm, edited 1 time in total.

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

Post by FeyFre »

Взято на заметку во время странствования по исходникам AP, но надобности не было, осталось висеть в воздухе.

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

measuresConverter-test.js
Added option to round off measures and currencies.
Added option to sort measures alphabetically.
Window position in systems with multiple monitors should be correctly restored.
And something good things that I forgot, may be. :)

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

runScript.js
Improved speed of scripts list receiving, based on Instructor's OpenSaveMask.js.
Window position in systems with multiple monitors should be correctly restored.


Offline
Posts: 139
Joined: Fri Feb 12, 2010 11:33 am

Post by Deim0s »

Позвольте реквест на ещё одну полезную вещь: Unix time

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

Deim0s

Code: Select all

var unixTime = new Date().getTime(); // или задать числом
var date = new Date(unixTime);
WScript.Echo(
	date.toLocaleString() + "\n" +
	date.toUTCString() + "\n" +
	date.toString() + "\n" +
	date.getTime()
);
Обратно аналогично:

Code: Select all

var dateString = new Date().toString(); // или задать строкой
var date = new Date(dateString);
...

Offline
Posts: 139
Joined: Fri Feb 12, 2010 11:33 am

Post by Deim0s »

Infocatcher,
Я не разобрался как работает :). Выдаёт текущие время/дату:
Image
причём не правильно(?) (13 чисел).
Хотелось бы что то вроде:
Выделить в AkelPad время/дату (в GMT), к примеру в таком формате:
00:00:00 01.01.1999
Получить в Unix time:
915148800
и.т.д:
16:39:50 26.04.2011 > 1303835990
1303835990 > 16:39:50 26.04.2011
А если было бы возможно ещё выводить hex-значение, вообще сказка была бы:
01:13:28 02.04.2011
1301706808
4D967838
P.S. Хотя последнее можно получить с HexSel.
P.P.S. Поторопился, с HexSel не то.

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

Deim0s
Там в миллисекундах.
Для примера там задается исходная строка на основании текущего времени.

Вот пример для работы с выделенным текстом, маленькие значения считаются заданными в секундах:

Code: Select all

var date = AkelPad.GetSelText().replace(/^\s+|\s+$/g, "");
if(/^(\d+|0x[0-9a-f]+)$/i.test(date)) {
	date = Number(date);
	if(date < 3e9)
		date *= 1000;
}
date = new Date(date);
WScript.Echo(
	date.toLocaleString() + "\n" +
	date.toUTCString() + "\n" +
	date.toString() + "\n" +
	date.getTime() + "\n" +
	Math.round(date.getTime()/1000) + "\n" +
	"0x" + Math.round(date.getTime()/1000).toString(16)
);
Только дату текстом съест далеко не каждую – без дополнительной обработки не обойтись.

Offline
Posts: 139
Joined: Fri Feb 12, 2010 11:33 am

Post by Deim0s »

Infocatcher,
Там в миллисекундах.
Да, сообразил с опозданием :).
Вот пример для работы с выделенным текстом...
Спасибо! То что нужно, в сторону "Unix time > Обычные время/дата" работает отлично. А можно в обратную сторону "Обычные время/дата > Unix time"? В любом бы формате из таких: 00:00:00 01.01.1999 или 00:00:00 01/01/1999 или 01/01/1999 00:00:00. И вызывать бы разными командами 8).
Locked