XE系列雖然可以跨平臺,但是在跨平臺的道路上只是走了一小半的路,很多平臺下的接口都沒實現徹底,所以爲了某些功能,還必須自己去摸索。
想實現程序中可以內嵌瀏覽器的功能,但是Firemonkey還沒有對應的控件,
TMS 倒是提供了true native Mac OS-X application development, TMS mCL 以及 JVEsoft的組件包,提供了對應的web瀏覽器控件,但是都不是免費的,而且試用麼TMS的問題還是有很多,爲了省銀子,捲起袖子自己搞。
思路其實很簡單,蘋果已經提供了webkit的框架,我的firemonkey只要能調用他的框架,就能使用它的功能了。
這也是XE系列的思路。
現在要做的是如何翻譯Mac OS Api了,這還是第一次搞,所以還不知道怎麼弄,翻山越嶺搜了一下,發現翻譯想自己實現webview的只有一個信息http://stackoverflow.com/questions/9731817/webview-not-displaying-in-macos-using-delphi-xe2,他遇到了無法顯示出來的一個問題。我跑了他的代碼,發現XE2下的代碼已經不能在XE4下運行了,稍作修改後,程序可以正常運行了,但是一直沒有效果,真的很困惑,問題出在哪裏了呢?
在github上有搜到了類似的代碼,看代碼應該是日本人寫的https://gist.github.com/tokibito/6945988/raw/6770e1fd3f8b3c8fd2e0da5498248a7e79f73944/Unit1.pas,還是打不開網頁。
於是發帖求助,一個老外給出了實現的方案,真心感謝,也不得不佩服他們。
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs,
FMX.StdCtrls, Macapi.CocoaTypes, Macapi.Foundation, Macapi.AppKit,
Macapi.ObjectiveC, FMX.Platform.Mac;
type
WebFrameClass = interface(NSObjectClass)
['{7BE750C8-DFEC-4870-851A-12DBCB0B78F6}']
end;
WebFrame = interface(NSObject)
['{BCFA04BE-41AB-4B78-89C0-3330F12C7695}']
procedure loadRequest(request: NSURLRequest); cdecl;
end;
TWebFrame = class(TOCGenericImport<WebFrameClass, WebFrame>) end;
WebViewClass = interface(NSViewClass)
['{0D9F44B7-09FD-4E35-B96E-8DB71B9A2537}']
{class} function canShowMIMEType(MIMEType: NSString): Boolean; cdecl;
end;
WebView = interface(NSView)
['{C36D8016-2FCB-49F0-BA1C-C9913A37F9AC}']
procedure clos; cdecl;
procedure setHostWindow(hostWindow: NSWindow); cdecl;
function initWithFrame(frame: NSRect; frameName: NSString; groupName: NSString): Pointer; cdecl;
function mainFrame: WebFrame; cdecl;
end;
TWebView = class(TOCGenericImport<WebViewClass, WebView>) end;
TOCLocalAccess = class(TOCLocal);
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
MyWebView: WebView;
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
var
PWebView: Pointer;
FwkMod: HMODULE;
urlStr: NSURL;
urlreq: NSURLRequest;
ObjTOC: TOCLocal;
MyView: NSView;
const
WebKitFWK: string = '/System/Library/Frameworks/WebKit.framework/WebKit';
begin
FwkMod := System.SysUtils.LoadLibrary(PWideChar(WebKitFWK)); //必須要加
MyView := WindowHandleToPlatform(Form1.Handle).View;
PWebView := TWebView.Alloc.initWithFrame(MakeNSRect(10, 10, 200, 200), nil, nil);
MyWebView := TWebView.Wrap(PWebView);
MyView.addSubview(MyWebView);
urlStr := TNSURL.Wrap(TNSURL.Alloc.initWithString(NSSTR('http://www.baidu.com/'))); // never ever call initWith... on an object created with "create". Some of these already fail on Mavericks, some may fail in the future
urlreq := TNSURLRequest.Create; // fixing this is left as an exercise for the reader :) see previous line
urlreq.initWithURL(urlstr); // .....
MyWebView.mainFrame.loadRequest(urlreq);
urlreq.release; // if you call alloc or create, you also have to call release, otherwise you will leak your object (create rule)
// same for urlstr, ...
end;
end.
var
PWebView: Pointer;
FwkMod: HMODULE;
urlStr: NSURL;
urlreq: NSURLRequest;
ObjTOC: TOCLocal;
MyNSWindow : NSWindow;
MyView: NSView;
const
WebKitFWK: string = '/System/Library/Frameworks/WebKit.framework/WebKit';
begin
FwkMod := System.SysUtils.LoadLibrary(PWideChar(WebKitFWK));
{//方法一
ObjTOC := (WindowHandleToPlatform(Form1.Handle).Handle as TOCLocal);
MyNSWindow := NSWindow(TOCLocalAccess(ObjTOC).Super);}
//方法二
MyNSWindow := WindowHandleToPlatform(Form1.Handle).Wnd;
PWebView := TWebView.Alloc.initWithFrame(MakeNSRect(0, 0, 200, 200), nil, nil);
MyWebView := TWebView.Wrap(PWebView);
MyWebView.setHostWindow(MyNSWindow);
//導致錯誤的地方
//urlStr := TNSURL.Create;
//urlstr.initWithString(NSSTR('http://www.google.com.hk/'));
urlStr := TNSURL.Wrap(TNSURL.Alloc.initWithString(NSSTR('http://www.google.com.hk/')));
urlreq := TNSURLRequest.Create;
urlreq.initWithURL(urlstr);
MyWebView.mainFrame.loadRequest(urlreq);
MyNSWindow.setContentView(MyWebView);
end;