Расширение проектора: Продолжение 5. Первое приложение.
Ничтоже сумняшеся, написал "блокнот" на флэше.
Что может программа:
-открывать, редактировать и сохранять текстовые файлы;
-сохранять настройки в реестре;
-можно передавать параметры в командной строке, а именно файл, который нужно открыть;
-стандартные хоткеи (Ctrl+S и т.д.)
Вобщем, почти полностью воспроизводит функционал обычного блокнота Windows.
Скачать скомпиленную программу можно здесь:
http://mdm-zinc.narod.ru/notepad.zip
В качестве иллюстрации привожу еще исходник: (AS 2.0)
Код:
import mx.controls.TextArea;
import extprojector.*;
class gui.Notepad extends MovieClip
{
private var ta:TextArea;
private var isSaved:Boolean = true;
private var title:String = "Flash Блокнот: ";
private var fileFilter:String = "Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)|*.*||";
private var hkSave:Number = 0;
private var hkOpen:Number = 0;
private var hkNew:Number = 0;
private var hkQuit:Number = 0;
private var hkPrnt:Number = 0;
private var sHeight:Number = 0;
private var sWidth:Number = 0;
private var sLeft:Number = 0;
private var sTop:Number = 0;
private var sFile:String = "";
private var sFontName:String = "Lucida Console";
private var sFontSize:String = "14";
private var sFontStyle:String = "normal";
private var sFontWeight:String = "none";
private var sFontUnderline:String = "none";
private var sFontColor:String = "0x000000";
private var sWordWrap:Boolean = false;
private var cmd:String = "";
private var regKey:String = "HKEY_CURRENT_USER\\Software\\FlashNotepad2";
public function Notepad()
{
super();
Stage.align = "TL";
Stage.scaleMode = "NoScale";
FlrunEx.initialize();
FlrunEx.addEventHandler(FlrunEx.EVENT_INIT, this);
}
private function SIZECHANGED(e:ExtEvent):Void
{
ta.setSize(e.params[1], e.params[2]);
}
private function change(e:Object):Void
{
isSaved = false;
}
private function INIT(e:ExtEvent):Void
{
cmd = e.params[0];
FlrunEx.removeEventHandler(FlrunEx.EVENT_INIT, this);
ta = _root.createClassObject(TextArea, "ta", 10);
ta.addEventListener("change", this);
PMenu.removeMainMenu();
PMenu.addEventHandler(PMenu.EVENT_MAINMENUCLICK, this);
/*var xml:String = "<menu>";
xml += "<tab label='Файл'>";
xml += "<item label='Создать... Ctrl+N' id='457'/>";
xml += "<item label='Открыть... Ctrl+O' id='458'/>";
xml += "<item label='Сохранить Ctrl+S' id='459'/>";
xml += "<item label='Сохранить как...' id='460'/>";
xml += "<separator/>";
xml += "<item label='Выход Ctrl+Q' id='461'/>";
xml += "</tab>";
xml += "<tab label='Вид'>";
xml += "<item label='Переносить по словам' id='33'/>";
xml += "<item label='Не переносить по словам' id='34'/>";
xml += "<separator/>";
xml += "<item label='Шрифт' id='35'/>";
xml += "</tab>";
xml += "<tab label='Справка'>";
xml += "<item label='О программе' id='1'/>";
xml += "</tab>";
xml += "</menu>";
PMenu.setMainMenu(xml);*/
PMenu.setMainMenuFromResource(602);
PMenu.setItemState(459, PMenu.STATE_DISABLED | PMenu.STATE_GRAYED);
PMenu.setRightClickMenuView(PMenu.VIEW_NOALL);
PMenu.setTextMenuView(PMenu.VIEW_RUSSIAN);
hkSave = PInput.registerHotKey(PInput.MOD_CONTROL, "S");
hkOpen = PInput.registerHotKey(PInput.MOD_CONTROL, "O");
hkNew = PInput.registerHotKey(PInput.MOD_CONTROL, "N");
hkQuit = PInput.registerHotKey(PInput.MOD_CONTROL, "Q");
PInput.addEventHandler(PInput.EVENT_HOTKEY, this);
PWindow.setIconFomResource(275, "shell32.dll");
PWindow.center();
PWindow.addEventHandler(PWindow.EVENT_SIZECHANGED, this);
PWindow.addEventHandler(PWindow.EVENT_CLOSE, this);
getSettings();
}
private function MAINMENUCLICK(e:ExtEvent):Void
{
var p:Number = Number(e.params[0]);
switch (p) {
case 1 :
PDialogs.msgBox("Текстовый редактор \"Flash Блокнот\".\nAS version: 2.0\nExtension: lcevt.dll (v 1.0.0.0)\n\nAuthor: alexcon314.\nEmail: alexcon314@rambler.ru", 0, "О программе:");
return;
case 458 :
open("");
break;
case 459 :
save(sFile);
break;
case 460 :
save("");
break;
case 461 :
CLOSE(null);
break;
case 457 :
newFile();
break;
case 35 :
setFont();
break;
case 34 :
ta.wordWrap = false;
break;
case 33 :
ta.wordWrap = true;
break;
}
}
private function HOTKEY(e:ExtEvent):Void
{
var p:Number = Number(e.params[0]);
switch (p) {
case hkOpen :
open();
break;
case hkSave :
save(sFile);
break;
case hkQuit :
CLOSE(null);
break;
case hkNew :
newFile();
break;
}
}
private function setFont():Void
{
var str:String = PDialogs.FontDialog();
if (!str) return;
var tmp:Array = str.split(FlrunEx.dlm);
var bgr:String = tmp[5];
var rgb:String = "0x" + bgr.substr(6, 2) + bgr.substr(4, 2) + bgr.substr(2, 2);
sFontName = tmp[0];
sFontSize = tmp[1];
sFontStyle = (Number(tmp[3]) == 1 ) ? ("italic") : ("normal");
sFontWeight = (Number(tmp[2]) == 700) ? ("bold" ) : ("none");
sFontUnderline = (Number(tmp[4]) == 1 ) ? ("underline") : ("none" );
sFontColor = rgb;
applyFontStyle();
}
private function applyFontStyle():Void
{
ta.setStyle("fontFamily", sFontName);
ta.setStyle("fontSize", sFontSize );
ta.setStyle("fontWeight", sFontWeight);
ta.setStyle("fontStyle", sFontStyle);
ta.setStyle("textDecoration", sFontUnderline);
ta.setStyle("color", sFontColor);
ta.wordWrap = sWordWrap;
}
private function getSettings():Void
{
var isKey:Boolean = PRegistry.keyExists(regKey);
if (!isKey) {
var tmp:Array = PWindow.getClientRect();
ta.setSize( tmp[2], tmp[3]);
applyFontStyle();
PRegistry.createKey(PRegistry.HKCU + "\\Software", "FlashNotepad2");
if (cmd) sFile = cmd;
if(!sFile || !open(sFile)) newFile();
return ;
}
sWidth = PRegistry.getDWORDValue (regKey, "sWidth");
sHeight = PRegistry.getDWORDValue (regKey, "sHeight");
sTop = PRegistry.getDWORDValue (regKey, "sTop");
sLeft = PRegistry.getDWORDValue (regKey, "sLeft");
sFontName = PRegistry.getStringValue(regKey, "sFontName");
sFontSize = PRegistry.getStringValue(regKey, "sFontSize");
sFontStyle = PRegistry.getStringValue(regKey, "sFontStyle");
sFontWeight = PRegistry.getStringValue(regKey, "sFontWeight");
sFontUnderline = PRegistry.getStringValue(regKey, sFontUnderline");
sFontColor = PRegistry.getStringValue(regKey, "sFontColor");
sFile = PRegistry.getStringValue(regKey, "sFile");
sWordWrap = Boolean(PRegistry.getDWORDValue(regKey, "sWordWrap"));
if (!PFileSystem.exists(sFile)) sFile = "";
if (cmd) sFile = cmd;
applyFontStyle();
PWindow.setRect([sLeft, sTop, sWidth, sHeight]);
var tmp:Array = PWindow.getClientRect();
ta.setSize( tmp[2], tmp[3]);
ta.wordWrap = sWordWrap;
if(!sFile || !open(sFile)) newFile();
}
private function saveSettings():Void
{
var tmp:Array = PWindow.getRect();
if(tmp[0] >= 0 && tmp[1] >= 0){
PRegistry.setDWORDValue(regKey, "sLeft", tmp[0] );
PRegistry.setDWORDValue(regKey, "sTop", tmp[1] );
PRegistry.setDWORDValue(regKey, "sWidth", tmp[2] );
PRegistry.setDWORDValue(regKey, "sHeight", tmp[3]);
}
PRegistry.setStringValue(regKey, "sFontName", sFontName );
PRegistry.setStringValue(regKey, "sFontSize", sFontSize );
PRegistry.setStringValue(regKey, "sFontStyle", sFontStyle );
PRegistry.setStringValue(regKey, "sFontWeight", sFontWeight );
PRegistry.setStringValue(regKey, "sFontUnderline", sFontUnderline );
PRegistry.setStringValue(regKey, "sFontColor", sFontColor );
PRegistry.setDWORDValue(regKey, "sWordWrap", Number(ta.wordWrap) );
PRegistry.setStringValue(regKey, "sFile", getPathToSave());
}
private function newFile():Void
{
if (checkForSave()) return;
PMenu.setItemState(459, PMenu.STATE_DISABLED | PMenu.STATE_GRAYED);
PMenu.setItemState(460, PMenu.STATE_ENABLED);
ta.text = "";
sFile = "";
PWindow.setTitle(title + "новый документ");
}
private function checkForSave():Boolean
{
if (isSaved) return false;
var res:Number = PDialogs.msgBox( "Сохранить изменения в текущем документе?", PDialogs.ICON_QUESTION + PDialogs.BUTTON_YES_NO_CANCEL, title + getFileName(sFile));
if (res == PDialogs.RESULT_CANCEL)return true;
if (res == PDialogs.RESULT_NO )return false;
save(sFile);
return false;
}
private function open(file:String):Boolean
{
var fileToOpen:String = file;
if (!file) { fileToOpen = PDialogs.OpenFileDialog (fileFilter); }
if (!fileToOpen) return false;
var pFile:PFile = new PFile();
if (pFile.create(fileToOpen, PFile.ACCESS_READ, PFile.ACCESS_SHARE_READ)) {
sFile = fileToOpen;
PWindow.setTitle(title + getFileName(sFile));
var sz:Number = pFile.size;
var str:String = pFile.readString(sz);
if (!str && sz != 0) {
PDialogs.errorBox();
pFile.close();
return false;
}
ta.text = str;
isSaved = true;
PMenu.setItemState(459, PMenu.STATE_ENABLED);
pFile.close();
return true;
}else
PDialogs.errorBox();
return false;
}
private function save(file:String):Void
{
var fileToSave:String = file;
if (!file) { fileToSave = PDialogs.SaveFileDialog (fileFilter); }
if (!fileToSave) return;
var fileName:String = getFileName(fileToSave);
var ind:Number = fileName.lastIndexOf(".");
if (ind < 0) { fileToSave += ".txt"; fileName += ".txt"; }
var pFile:PFile = new PFile();
if (pFile.create(fileToSave, PFile.ACCESS_WRITE, PFile.ACCESS_SHARE_WRITE, PFile.MODE_CREATE_ALWAYS))
{
sFile = fileToSave;
var len:Number = pFile.writeString(ta.text);
if (len != 0) {
PWindow.setTitle(title + fileName);
pFile.close();
}
else
PDialogs.errorBox();
}
isSaved = true;
PMenu.setItemState(459, PMenu.STATE_ENABLED);
}
private function CLOSE(e:ExtEvent):Void
{
saveSettings();
if (checkForSave())return;
PInput.unregisterHotKey(hkSave);
PInput.unregisterHotKey(hkOpen);
PInput.unregisterHotKey(hkNew );
PInput.unregisterHotKey(hkQuit);
PWindow.close();
}
private function getFileName(file:String):String
{
return file.substr(1 + file.lastIndexOf("\\"))
}
private function getPathToSave():String
{
if (sFile.indexOf(":") < 0 && sFile) { // not a full path
return FlrunEx.current_dir + "\\" + sFile;
}else
return sFile;
}
}
Всего комментариев 23
Комментарии
|
|
|
Что-то я не пойму.
notepad.exe - это стандартный неизмененный проектор флеша? А как он тогда с dll-ками общается? |
|
|
|
стандартный неизмененный проектор флеша - это libavm.dll (если неустраивает название, можно поменять), lcevt.dll - это сам экстенжн. notepad.exe по сути просто лаунчер. Он стартует проектор, грузит эксенжн и отваливает, больше он ничего не делает. Вобще, он один и тот же для любого приложения, просто с него начинается вся работа.
Мне пришла в голову "гениальная" идея: зачем иметь два экзешника, можно запарить и впасть в непонятки, чего запускать-то? Вот я и переименовал стандартный неизменный проектор в длл. Работает, естественно, он. И общается он с lcevt.dll через шаредобжект, как - описано в предыдущем посте блога за номером 4. А что, вполне приглядное приложение: экзешник, две либы к нему и все. Вот такая вот немудреная маскировка. Можно и через fscommand запускаться, но тут по-неволе окно проектора первым появится, и все усилия по настройке внешнего вида окна, смена меню, иконки, к примеру, будут видны. Это можно использовать, когда с окном ничего делать не предполагается. А так проектор стартуется как хидден, делаем с ним все что нужно и показываем во всей красе. (метод PWindow.show() вызывается здесь неявно в обработчике INIT()). Если запутал, прошу прощения. Есть идеи как сделать лучше - предлагай. ЗЫ. Есть версия блокнота и на AS 3.0, код практически идентичен, либа, лаунчер те же. Кажется удалось добиться соместимости с обоими версиями АС. Версии плеера только 9, 10 и строго не дебуг. На дебуг версиях не работает, под них я экстенжн просто не затачивал. |
|
|
Обновил(-а) alexcon314 24.02.2010 в 23:09
|
|
|
|
Тутор, конечно надо бы... только пока спешить с выпуском не буду. Хочу сделать еще пару приложений тестовых. Опыт разработки блокнота помог выявить много важных моментов. Короче, обкатка.
Вкратце: есть набор классов оболочки (package extprojector); делаем их импорт, кодим, компилим свф; делаем из свф обычный проектор; именуем его libavm.dll (просто сменили имя, можно сразу его задать при создании проектора, блин, сам не могу еще привыкнуть к это фиче))); собираме в одну папочку лаунчер, lcevt.dll, libavm.dll; запускаем лаунчер; У меня все это получилось автоматизировать под FD, ну, то есть, настраиваем пути, работаем как обычно, потом жмем билд, а в постбилде прописан батник на сборку проектора и запуск лаунчера. Тут же смотрим, что получилось в итоге. Вобщем, все компилится, именуется, складывается куда нужно и запускается одной кнопкой прямо из FD. Кастомизация файлов лаунчера и экстенжена возможна своими силами. Сам лаунчер можно обозвать как угодно, резхакером иконку ему поменять и сконфигурять его на запуск проектора с другим именем (не libavm.dll, если оно не устраивает), указать ему инишник, передать параметры запуска и т.п. lcevt.dll в своих ресурсах содержит некоторые необходимые для работы экстенжена данные, ну и опять же резхакером в ее ресурсы можно зашить кастомные данные: иконки, меню, что-то там еще.. не помню, по потребности, вобщем. А, да, можно будет как я предполагаю в будущем в ресы пихать все что хочешь, хоть свф-ы, хоть пдф-ы, хмл-ы, хтмл-ы, скрипты, картинки, музон, фильмы, екзешники (этт я загнул ))) и проч. В классах оболочки будут(уже частично есть) методы для работы с ресурсами длл. Конечно, можно отдельную длл под ресурсы использовать или несколько. Че-то уже не "вкратце" получается. Пока остановлюсь)). |
|
|
Обновил(-а) alexcon314 25.02.2010 в 14:02
|
|
|
|
Цитата:
Наверное, можно сделать раз и навсегда пустой проектор (главное в нем - ФП) и грузить туда уже нужные swf-ки.
Опсс.. наверно я не так тебя понял. Я имею в виду, что совсем пустой проектор - это просто автономный плеер, в принципе можно попробовать запускать лаунчером этот самый плеер с параметром-путем к свфу, тогда должно работать, в принципе.. надо попробовать. Пока такую возможность не предусматривал.. Я про другое сначала подумал: скомпиленный раз и навсегда свф-загрузчик зашиваем в проектор, а приложение как таковое им грузится. Я так делал на цинке. |
|
|
Обновил(-а) alexcon314 25.02.2010 в 17:21
|
|
|
|
Цитата:
А совсем пустой проектор как сделать легально? Я не знаю.
|
|
|
|
Цитата:
standalone player? или его нельзя распространять?
|
|
|
|
Цитата:
а он что в экзешнике, что в dll-ке остался без изменений
Из твоих слов можно сделать вывод, что я включил проектор-плеер в состав стороннего (по отношению к адобу) модуля, ну типа сделал длл, в ее ресы засунул проектор и использую, а это было бы скорее всего нарушением. Так вот это не так. Переименуйте длл (libavm.dll) в ехе и вы получите проектор чистой воды. Я его, конечно, использую, но по прямому назначению - воспроизводить свф-ролики. И он лежит, как и положено, отдельным файлом, никто его не крал и не ломал. И вообще, хватит о грустном)). В конце концов, можно просто забыть (забить) именовать проектор в ехе))(шутка). |
|
|
Обновил(-а) alexcon314 26.02.2010 в 22:35
|
|
|
|
alexcon314, кстати, а как насчет Линукса? Или проект заточен под Винду?
|
|
|
|
В текущем состоянии только под винду. Боюсь, что портировать на линукс будет трудно. Сам код методов, ну типа записать в файл, создать папку и т.п., по идее, портируется, там в большинстве нет ничего сугубо от винды (реестр разве что), ну функции поправить/заменить, вопрос времени. А вот портировать двиг с инжектом в рантайм, перхватом обращений к шаредам и ЛЦ - этот вопрос потребует намного больше усилий. Скорее всего, в том виде, как он есть двиг вообще не портабелен..
ЗЫ. Недавно тут в ветке про цинк отписались, что финбоксы тоже на линуксы не портируют свой проект потому, что.... не знают как перехватить у флэша обращения к файловой системе. О как. Не объединить ли с ними усилия? .ЗЫЫ Хоть бы уж под винду выложить что-нибудь... а ты уж и на линукс замахнулся... Да, тут человек пытался на питоне враппер написать для флэш-плагина, может он чем порадует. |
|
|
Обновил(-а) alexcon314 31.03.2010 в 15:14
|
|
|
|
Не повезло. Меня как раз момент перехвата/подмены обращения ФП к ОС интересовал на Линуксе в первую очередь...
|
|
|
|
да ладно.. было бы желание))
https://www.evilfingers.com/publicat....hook.lite.pdf |
|
|
|
Добрый день. Жду не дождусь выхода программы. Когда же это случится?
|
|
|
|
Надеюсь, что скоро. Месяц-полтора.. Обстоятельства не дают закончить.
|
Последние записи от alexcon314
- Пишем свою оболочку для FP под Windows. Шаг 6. (19.05.2011)
- Пишем свою оболочку для FP под Windows. Шаг 5. (18.05.2011)
- Пишем свою оболочку для FP под Windows. Шаг 4. (18.05.2011)
- Пишем свою оболочку для FP под Windows. Шаг 3. (18.05.2011)
- Пишем свою оболочку для FP под Windows. Шаг 2. (17.05.2011)












.