Я стремился следовать принципу KISS при решении этой задачи. Весьма полезными оказались следующие ресурсы: Предлагаемый способ основан на создании в Firefox невидимого окна для приёма сообщений. Это окно можно будет найти по имени класса и имени окна (я использую "Modus RP Class" и "Modus RP"). Для упрощения примера я буду передавать строку, но можно передать любую структуру. Также для упрощения в Web приложении будет вызываться функция window.alert(). В Delphi 2010 для отправки сообщения я на форму добавил кнопку TButton и обработчик события OnClick:
procedure TForm1.Button1Click(Sender: TObject);
var
s: String;
copyData: TCopyDataStruct;
targetHandle: HWND;
begin
s := 'Текущее время: ' + DateTimeToStr(Now());
copyData.lpData := PChar(s);
copyData.cbData := SizeOf(Char) * (Length(s) + 1);
targetHandle := FindWindow('Modus RP Class', 'Modus RP');
if targetHandle <> 0 then
SendMessage(targetHandle, WM_COPYDATA, Handle, Longint(@copyData));
end;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Call JavaScript Function</title>
<script type="text/javascript" language="javascript">
function getBrowserName() {
var browserName = "";
var ua = navigator.userAgent.toLowerCase();
if ( ua.indexOf("opera") != -1 )
browserName = "opera";
else if ( ua.indexOf("msie") != -1 )
browserName = "msie";
else if ( ua.indexOf("safari") != -1 )
browserName = "safari";
else if ( ua.indexOf("mozilla") != -1 )
if ( ua.indexOf("firefox") != -1 )
browserName = "firefox";
else
browserName = "mozilla";
return browserName;
};
if (getBrowserName() == "firefox") {
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
Components.utils.import("resource://gre/modules/ctypes.jsm");
var user32 = ctypes.open("user32.dll");
var kernel32 = ctypes.open("kernel32.dll");
const HWND_MESSAGE = -3;
const WM_COPYDATA = 74;
var lpszClassName = ctypes.char.array()("Modus RP Class");
var lpszWindowName = ctypes.char.array()("Modus RP");
const COPYDATASTRUCT = ctypes.StructType("COPYDATASTRUCT",
[
{dwData: ctypes.uintptr_t},
{cbData: ctypes.uint32_t},
{lpData: ctypes.voidptr_t}
]);
var DefWindowProc = user32.declare("DefWindowProcA", ctypes.winapi_abi, ctypes.int,
ctypes.voidptr_t, ctypes.int32_t, ctypes.int32_t, ctypes.int32_t);
function windowProcJSCallback(hWnd, uMsg, wParam, lParam) {
if (uMsg == WM_COPYDATA) {
var CD = COPYDATASTRUCT.ptr(lParam).contents;
var s = ctypes.cast(CD.lpData, ctypes.jschar.ptr).readString();
alert(s);
return ctypes.int(0);
} else
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
var WindowProcType = ctypes.FunctionType(ctypes.stdcall_abi, ctypes.int,
[ctypes.voidptr_t, ctypes.int32_t, ctypes.int32_t, ctypes.int32_t]).ptr;
var WindowProcPointer = WindowProcType(windowProcJSCallback);
var WNDCLASS = ctypes.StructType("WNDCLASS",
[
{ style: ctypes.uint32_t },
{ lpfnWndProc: WindowProcType },
{ cbClsExtra: ctypes.int32_t },
{ cbWndExtra: ctypes.int32_t },
{ hInstance: ctypes.voidptr_t },
{ hIcon: ctypes.voidptr_t },
{ hCursor: ctypes.voidptr_t },
{ hbrBackground: ctypes.voidptr_t },
{ lpszMenuName: ctypes.char.ptr },
{ lpszClassName: ctypes.char.ptr }
]);
var GetModuleHandle = kernel32.declare("GetModuleHandleA", ctypes.winapi_abi,
ctypes.voidptr_t, ctypes.char.ptr);
var hInstance = GetModuleHandle(null);
var wndclass = WNDCLASS();
wndclass.hInstance = hInstance;
wndclass.lpszClassName = lpszClassName;
wndclass.lpfnWndProc = WindowProcPointer;
var RegisterClass = user32.declare("RegisterClassA", ctypes.winapi_abi,
ctypes.uint32_t, WNDCLASS.ptr);
var UnregisterClass = user32.declare("UnregisterClassA", ctypes.winapi_abi,
ctypes.bool, ctypes.char.ptr, ctypes.voidptr_t);
var DestroyWindow = user32.declare("DestroyWindow", ctypes.winapi_abi,
ctypes.bool, ctypes.voidptr_t);
RegisterClass(wndclass.address());
var CreateWindowEx = user32.declare("CreateWindowExA", ctypes.winapi_abi,
ctypes.voidptr_t, ctypes.int, ctypes.char.ptr, ctypes.char.ptr, ctypes.int,
ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.voidptr_t,
ctypes.voidptr_t, ctypes.voidptr_t, ctypes.voidptr_t);
var win = CreateWindowEx(0, lpszClassName, lpszWindowName, 0, 0, 0, 0, 0,
ctypes.voidptr_t(HWND_MESSAGE), null, hInstance, null);
window.onunload = function () {
if (win && !win.isNull()) {
DestroyWindow(win);
UnregisterClass(lpszClassName, hInstance);
user32.close();
kernel32.close();
win = null;
}
};
} catch(ex) {}
}
</script>
</head>
<body>
<h1>Call JavaScript Function</h1>
</body>
Чтобы всё это работало, требуется дать разрешения в Firefox. Для этого нужно открыть в нём окно about:config и изменить свойство signed.applets.codebase_principal_support = true. Затем открыть файл C:/Users/.../AppData/Roaming/Mozilla/Firefox/Profiles/...default/prefs.js и добавить строки
user_pref("capability.principal.codebase.p<n>.granted", "UniversalXPConnect");
user_pref("capability.principal.codebase.p<n>.id", "http://<localhost:8080>");
user_pref("capability.principal.codebase.p<n>.subjectName", "");
Здравствуйте
ОтветитьУдалитьПодскажите пожалуйста как создать экземпляр класса который хранится в dll из javascript. С вызовом функций вроде понятно, а как классами пользоваться?