秋·风

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  276 随笔 :: 0 文章 :: 305 评论 :: 19万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

近日试用了D2Bridge Framework这个开源框架,体验还不错,lazarus终于有比较好的开源web框架。

一、简介

Web 技术:
根据VCL/FMX/LCL控件直接生成 Bootstrap 5 和最新 Web 技术兼容的响应式 HTML 代码

模板:
它已经带有模板,并且其 Web 界面可以与您的 VCL/FMX/LCL 项目不同,而无需更改其代码


D2Bridge独有功能

组件:

导出到 Web 时不需要其他组件。D2Bridge 识别并拦截您的可视组件

相同的代码库:
您可以使用项目中已有的相同代码和相同接口来编译适用于 Desktop 和 Web 的应用程序

集成服务器:
在为 Web 编译应用程序时,您可以在 3 个非常轻量级且功能强大的 Web 服务器(控制台、紧凑型和完整)之间进行选择

D2Bridge 向导:
集成到 Delphi 中的工具,可帮助您使用已包含的模板创建视觉丰富的应用程序

同步:
从简单的 'MessageDlg' 响应到 ShowModal 或 Timer,Web 上的所有内容都以与桌面上相同的方式工作

支持库大小:
使用的js比较轻巧,最精简的wwwroot目录只需8个文件,1.49MB。比unigui轻多了。

全部 Delphi/Lazarus:

D2Bridge 框架不需要除您已经使用的 Delphi/Lazarus以外的代码。根据 Delphi/Lazarus编写所有内容,D2Bridge 为您编写 Web 代码

自适应桌面浏览器和手机浏览器
详见下面的截图

缺点:

1、组件一些属性得手动添加才行没有设计时支持。
2、没设计时,不能所见所得。
3、除D2Bridge 向导外,提供了全部源代码,由于D2Bridge 向导外只提供ppu文件,必须使用lazarus官方版本及指定的indy片材才能安装,fpcupdeluxe安装的版本无法使用,D2Bridge 向导只在新建projce和form时才用到,不安装向导也能编译。

默认可以的标准可视控件:

TButton
TBitBtn
TButtonedEdit
TCheckBox
TCombobox
TDateTimePicker
TDBCheckBox
TDBCombobox
TDBEdit
TDBGrid
TDBLookupCombobox
TDBMemo
TDBText
TEdit
TEditButton
TImage
TLabel
TMainMenu
TMaskEdit
TMemo
TRadioButton
TSpeedButton
TStringGrid
TCurrencyEdit
TDateEdit
TDBDateEdit
第三方控件:
TJvCalcEdit
TJvDatePickerEdit
TJvDBCombobox
TJvDBDateEdit
TJvDbGrid
TJvDBLookupCombo
TJvDBUltimGrid
TJvValidateEdit
TRxDBCalcEdit
TRxLookupEdit
TSMDBGrid
TwwButton
TwwCheckBox
TwwDBComboBox
TwwDBComboDlg
TwwDBDateTimePicker
TwwDBEdit
TwwDBGrid
TwwDBLookupCombo
TwwDBLookupComboDlg
TwwDBRichEdit
TwwDBSpinEdit
TwwIncrementalSearch
TwwRadioButton
默认没启用第三方控件,需在D2Bridge.inc启用相关第三方控件
如果自定义控件,可在D2Bridge.Item.VCLObj.pas绑定自定义控件

二、普通工程文件及单元转为web和desktop两用模式

以下是将普通工程文件及单元转为Web和桌面2种兼容模式的步骤及注意事项。

使用D2Bridge的lazarus示例为基础,使用自己新建的Form。
1、新建Form2
1)首先改为Delphi模式,并在uses添加D2Bridge.Forms
2)将TForm2 = class(TForm)改为TForm2 = class(TD2BridgeForm)
3)添加procedure ExportD2Bridge; override并在实现部位将需要在web页面显示的控件添加到D2Bridge

复制代码
unit Unit2;

{$mode Delphi}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, DBGrids,
  D2Bridge.Forms;

type

  { TForm2 }

  TForm2 = class(TD2BridgeForm)
    Button1: TButton;
    DBGrid1: TDBGrid;
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Button1Click(Sender: TObject);
  private

  protected
    procedure ExportD2Bridge; override;//将form的控件添加到D2Bridge
  public

  end;

  {$IFDEF D2BRIDGE}
   Function Form2: TForm2;
  {$ELSE}
   var
     Form2: TForm2;
  {$ENDIF}

implementation

{$R *.lfm}

{$IFDEF D2BRIDGE}
 Function Form2: TForm2;
 begin
  Result:= TForm2(TForm2.GetInstance);
 end;
{$ENDIF}

procedure TForm2.Button1Click(Sender: TObject);
begin
  edit2.Text:=edit1.Text;
end;

procedure TForm2.ExportD2Bridge;
begin
  inherited;
  with D2Bridge.Items.Add do
  begin
    VCLObj(edit1);
    VCLObj(edit2);
    VCLObj(Button1);
    VCLObj(DBGrid1);
  end;
end;

end.
复制代码

2、修改Unit_D2Bridge_Server_Console.pas原来的unit1为你的unit

复制代码
  public
    class procedure Run;
  end;

implementation

uses
  Forms, Classes,
  ServerController, Unit2;
复制代码

修改class procedure TD2BridgeServerConsole.Run里原来的TForm名称:

复制代码
class procedure TD2BridgeServerConsole.Run;
begin
 D2BridgeServerController:= TD2BridgeServerController.Create(TApplication.Create(nil));
 vServerPort:= D2BridgeServerController.Prism.INIConfig.ServerPort(8888);
 vServerName:= D2BridgeServerController.Prism.INIConfig.ServerName('D2Bridge Server');


 D2BridgeServerController.PrimaryFormClass:= TForm2;

 D2BridgeServerController.Prism.Options.IncludeJQuery:= true;
复制代码

3、修改项目源代码
以下是完整的project.lpr,红色部分是定义Web和DeskTop模式的,蓝色部分是所有D2Bridge应用都要有的代码,不管是DeskTop或还是Web。

复制代码
program ControlsW32;

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

{$IFDEF d2bridge}
{$APPTYPE CONSOLE}
{$endif}

uses
{$IFDEF UNIX}
  cthreads, clocale,
{$ENDIF}
  Forms, indylaz, memdslaz, datetimectrls, Interfaces,
{$IFDEF d2bridge}
  ServerController,
  Unit2 {Form2},
  DemoControls_Session {DemoControlsSession},
  Unit_D2Bridge_Server_Console,
{$else}
  Unit2 in 'Unit2.pas' {Form2},
{$endif}
  D2Bridge.API.Mail.Adresses, D2Bridge.API.Mail.Config, D2Bridge.API.Mail,
  D2Bridge.API, D2Bridge.API.QRCode, D2Bridge.BaseClass,
  D2Bridge.FMXObj.TComboEdit, D2Bridge.FMXObj.TDateEdit,
  D2Bridge.FMXObj.TMenuBar, D2Bridge.Forms.Helper, D2Bridge.Forms,
  D2Bridge.FrameworkItem.DataWare, D2Bridge.FrameworkItem.GridColumns,
  D2Bridge.HTML.CSS, D2Bridge.HTML, D2Bridge.Image.Interfaces, D2Bridge.Image,
  D2Bridge.Instance, D2Bridge.Interfaces, D2Bridge.Item.Default,
  D2Bridge.Item.HTML.Accordion, D2Bridge.Item.HTML.Card.Footer,
  D2Bridge.Item.HTML.Card.Grid, D2Bridge.Item.HTML.Card.Group,
  D2Bridge.Item.HTML.Card.Header, D2Bridge.Item.HTML.Card.Image,
  D2Bridge.Item.HTML.Card, D2Bridge.Item.HTML.Carousel,
  D2Bridge.Item.HTML.FormGroup, D2Bridge.Item.HTML.Link,
  D2Bridge.Item.HTML.PanelGroup, D2Bridge.Item.HTML.Popup,
  D2Bridge.Item.HTML.QRCode, D2Bridge.Item.HTML.Row,
  D2Bridge.Item.HTML.SideMenu, D2Bridge.Item.HTML.Tabs,
  D2Bridge.Item.HTML.Upload, D2Bridge.Item.HTMLElement, D2Bridge.Item.Nested,
  D2Bridge.Item, D2Bridge.Item.VCLObj, D2Bridge.Item.VCLObj.Style,
  D2Bridge.ItemCommon.Add, D2Bridge.ItemCommon, D2Bridge.Lang.APP.Core,
  D2Bridge.Lang.APP.Term, D2Bridge.Lang.Arabic, D2Bridge.Lang.BaseClass,
  D2Bridge.Lang.Chinese, D2Bridge.Lang.Core.BaseClass, D2Bridge.Lang.Core.JSON,
  D2Bridge.Lang.Core, D2Bridge.Lang.Czech, D2Bridge.Lang.English,
  D2Bridge.Lang.French, D2Bridge.Lang.German, D2Bridge.Lang.Interfaces,
  D2Bridge.Lang.Italian, D2Bridge.Lang.Japanese, D2Bridge.Lang.Portuguese,
  D2Bridge.Lang.Russian, D2Bridge.Lang.Spanish, D2Bridge.Lang.Term.BaseClass,
  D2Bridge.Lang.Term, D2Bridge.Lang.Util, D2Bridge.Manager, D2Bridge.Messages,
  D2Bridge, D2Bridge.Prism.Button, D2Bridge.Prism.ButtonedEdit,
  D2Bridge.Prism.CheckBox, D2Bridge.Prism.Combobox, D2Bridge.Prism.DBCheckBox,
  D2Bridge.Prism.DBCombobox, D2Bridge.Prism.DBEdit, D2Bridge.Prism.DBGrid,
  D2Bridge.Prism.DBLookupCombobox, D2Bridge.Prism.DBMemo, D2Bridge.Prism.DBText,
  D2Bridge.Prism.Default, D2Bridge.Prism.Edit, D2Bridge.Prism.Form,
  D2Bridge.Prism.Image, D2Bridge.Prism.Item, D2Bridge.Prism.MainMenu,
  D2Bridge.Prism.Memo, D2Bridge.Prism.Menu, D2Bridge.Prism,
  D2Bridge.Prism.StringGrid, D2Bridge.Prism.Text, D2Bridge.Render.HTMLType,
  D2Bridge.Render, D2Bridge.ServerControllerBase, D2Bridge.Types, D2Bridge.Util,
  D2Bridge.VCLObj.Override, D2Bridge.VCLObj.TButton,
  D2Bridge.VCLObj.TButtonedEdit, D2Bridge.VCLObj.TCheckBox,
  D2Bridge.VCLObj.TCombobox, D2Bridge.VCLObj.TDateTimePicker,
  D2Bridge.VCLObj.TDBCheckBox, D2Bridge.VCLObj.TDBCombobox,
  D2Bridge.VCLObj.TDBEdit, D2Bridge.VCLObj.TDBGrid,
  D2Bridge.VCLObj.TDBLookupCombobox, D2Bridge.VCLObj.TDBMemo,
  D2Bridge.VCLObj.TDBText, D2Bridge.VCLObj.TEdit, D2Bridge.VCLObj.TImage,
  D2Bridge.VCLObj.TLabel, D2Bridge.VCLObj.TMainMenu, D2Bridge.VCLObj.TMaskEdit,
  D2Bridge.VCLObj.TMemo, D2Bridge.VCLObj.TRadioButton,
  D2Bridge.VCLObj.TSpeedButton, D2Bridge.VCLObj.TStringGrid,
  D2Bridge.Vendor.DelphiZXIngQRCode, D2Bridge.VCLObj.TCurrencyEdit,
  D2Bridge.VCLObj.TcxCheckBox, D2Bridge.VCLObj.TcxComboBox,
  D2Bridge.VCLObj.TcxDateEdit, D2Bridge.VCLObj.TcxDBCheckBox,
  D2Bridge.VCLObj.TcxDBComboBox, D2Bridge.VCLObj.TcxDBDateEdit,
  D2Bridge.VCLObj.TcxDBLabel, D2Bridge.VCLObj.TcxDBLookupComboBox,
  D2Bridge.VCLObj.TcxDBMemo, D2Bridge.VCLObj.TcxDBTextEdit,
  D2Bridge.VCLObj.TcxGridDBTableView, D2Bridge.VCLObj.TcxImage,
  D2Bridge.VCLObj.TcxLabel, D2Bridge.VCLObj.TcxMemo,
  D2Bridge.VCLObj.TcxRadioButton, D2Bridge.VCLObj.TcxTextEdit,
  D2Bridge.VCLObj.TDateEdit, D2Bridge.VCLObj.TDBDateEdit,
  D2Bridge.VCLObj.TJvDbGrid, D2Bridge.VCLObj.TJvDBLookupCombo,
  D2Bridge.VCLObj.TJvDBUltimGrid, D2Bridge.VCLObj.TJvValidateEdit,
  D2Bridge.VCLObj.TRxDBCalcEdit, D2Bridge.VCLObj.TRxLookupEdit,
  D2Bridge.VCLObj.TSMDBGrid, D2Bridge.VCLObj.TwwDBComboBox,
  D2Bridge.VCLObj.TwwDBComboDlg, D2Bridge.VCLObj.TwwDBEdit,
  D2Bridge.VCLObj.TwwDBGrid, D2Bridge.VCLObj.TwwCheckBox,
  D2Bridge.VCLObj.TwwDBLookupCombo, D2Bridge.VCLObj.TwwDBLookupComboDlg,
  D2Bridge.VCLObj.TwwDBRichEdit, D2Bridge.VCLObj.TwwIncrementalSearch,
  D2Bridge.VCLObj.TwwRadioButton, D2Bridge.VCLObj.TJvDBDateEdit,
  Prism.BaseClass, Prism.BaseClass.Sessions, Prism.BaseClass.Timer,
  Prism.Button, Prism.ButtonedEdit, Prism.CallBack, Prism.Carousel,
  Prism.CheckBox, Prism.Clipboard, Prism.Combobox, Prism.ControlGeneric,
  Prism.Cookie, Prism.CSS.Bootstrap.Button, Prism.DataWare.Field,
  Prism.DataWare.Mapped, Prism.DBCheckBox, Prism.DBCombobox, Prism.DBEdit,
  Prism.DBGrid, Prism.DBLookupCombobox, Prism.DBMemo, Prism.DBText, Prism.Edit,
  Prism.Events, Prism.Font.Awesome, Prism.Form.Timer, Prism.Forms.Controls,
  Prism.Forms, Prism.Grid.Columns.Buttons, Prism.Grid.Columns, Prism.Grid,
  Prism.HTMLElement, Prism.Image, Prism.Interfaces, Prism.JSONHelper,
  Prism.Link, Prism.Log, Prism.MainMenu, Prism.Memo, Prism.Menu.Group,
  Prism.Menu.Item, Prism.Menu.Items, Prism.Menu.Link, Prism.Menu,
  Prism.Menu.SubMenu, Prism, Prism.QRCode, Prism.Server.Functions,
  Prism.Server.HTML.Headers, Prism.Server.HTML, Prism.Server.HTTP.Commom,
  Prism.Server.TCP, Prism.Session.Event, Prism.Session.Helper,
  Prism.Session.Info, Prism.Session, Prism.Session.Thread,
  Prism.Session.Thread.Proc, Prism.SessionBase, Prism.SideMenu,
  Prism.StringGrid, Prism.Tabs, Prism.Text.Mask, Prism.Text, Prism.Types,
  Prism.URI, Prism.UserSessionBase, Prism.Util, Prism.WebSocketContext,
  Prism.Card, D2Bridge.JSON, D2Bridge.VCLObj.TEditButton,
  D2Bridge.Item.HTML.Image;

{$R *.res}

begin
  Application.Scaled:=True;
  Application.Initialize;
  {$ifdef d2bridge}
  Application.MainFormOnTaskbar:= False;
  TD2BridgeServerConsole.Run;
  {$else}
  Application.CreateForm(TForm2, Form2);
  Application.Run;
  {$endif}
end.  
复制代码

 如果编译为Web应用,则需添加:

如果编译为桌面应用则将Custom options清空或改名。 
经以上修改后,这个demo就可以用同1份代码实现Web和桌面2种模式的应用。

三、编译后的应用运行截图
1.桌面应用:

 2. Web服务:


3.win11 浏览器:

 4.手机浏览器:

 四、小技巧:

每个D2Bridge应用打开时浏览器Tab上的名称默认是"D2Bridge"

 如果要修改这个名称,打开Unit_D2Bridge_Server_Console.pas在class procedure TD2BridgeServerConsole.Run添加:

 D2BridgeServerController.APPName:='lazarus Web测试';     

详见:

复制代码
class procedure TD2BridgeServerConsole.Run;
begin
 D2BridgeServerController:= TD2BridgeServerController.Create(TApplication.Create(nil));
 vServerPort:= D2BridgeServerController.Prism.INIConfig.ServerPort(8888);
 vServerName:= D2BridgeServerController.Prism.INIConfig.ServerName('D2Bridge Server');


 D2BridgeServerController.PrimaryFormClass:= TForm2;

 D2BridgeServerController.Prism.Options.IncludeJQuery:= true;

 //D2BridgeServerController.Prism.Options.DataSetLog:= true;

 D2BridgeServerController.Prism.Options.CoInitialize:= true;

 //D2BridgeServerController.Prism.Options.VCLStyles:= false;

 //Uncomment to Dual Mode force http just in Debug Mode
 //if IsDebuggerPresent then
 // D2BridgeServerController.Prism.Options.SSL:= false
 //else
 //D2BridgeServerController.Prism.Options.SSL:= true;

 D2BridgeServerController.Languages:= [TD2BridgeLang.English,TD2BridgeLang.Portuguese];

 if D2BridgeServerController.Prism.Options.SSL then
 begin
  //Cert File
  D2BridgeServerController.Prism.SSLOptions.CertFile:= '';
  //Cert Key Domain File
  D2BridgeServerController.Prism.SSLOptions.KeyFile:= '';
  //Cert Intermediate (case Let�s Encrypt)
  D2BridgeServerController.Prism.SSLOptions.RootCertFile:= '';
 end;

 D2BridgeServerController.Prism.Options.PathJS:= 'js';
 D2BridgeServerController.Prism.Options.PathCSS:= 'css';

 DisplayStartConfigServer;

 D2BridgeServerController.Port:= vServerPort;
 D2BridgeServerController.ServerName:= VServerName;

 D2BridgeServerController.StartServer;
 D2BridgeServerController.APPName:='lazarus Web测试';//可自行设置Tab上的名称

  try
    while D2BridgeServerController.Started do
    begin
      DisplayInfo;
      Sleep(100);
      SetCursorPosition(0, 0);
    end;
  except
    on E: Exception do
      Writeln('Error: ', E.Message);
  end;
end;
复制代码

设置后重新编译运行,再次打开浏览器就可以:



 

 

 2024-12-10:
修改ExportD2Bridge增加自动添加控件到D2Bridge

复制代码
{$IFDEF D2BRIDGE}
procedure TForm2.ExportD2Bridge;
  procedure AddControls(AControl: TComponent);
  var
    i,j: Integer;

    ComponentType :array [0..49] of string=(
    'TButton',
    'TBitBtn',
    'TButtonedEdit',
    'TCheckBox',
    'TCombobox',
    'TDateTimePicker',
    'TDBCheckBox',
    'TDBCombobox',
    'TDBEdit',
    'TDBGrid',
    'TDBLookupCombobox',
    'TDBMemo',
    'TDBText',
    'TEdit',
    'TEditButton',
    'TImage',
    'TLabel',
    'TMainMenu',
    'TMaskEdit',
    'TMemo',
    'TRadioButton',
    'TSpeedButton',
    'TStringGrid',
    'TCurrencyEdit',
    'TDateEdit',
    'TDBDateEdit',
    'TJvCalcEdit',
    'TJvDatePickerEdit',
    'TJvDBCombobox',
    'TJvDBDateEdit',
    'TJvDbGrid',
    'TJvDBLookupCombo',
    'TJvDBUltimGrid',
    'TJvValidateEdit',
    'TRxDBCalcEdit',
    'TRxLookupEdit',
    'TSMDBGrid',
    'TwwButton',
    'TwwCheckBox',
    'TwwDBComboBox',
    'TwwDBComboDlg',
    'TwwDBDateTimePicker',
    'TwwDBEdit',
    'TwwDBGrid',
    'TwwDBLookupCombo',
    'TwwDBLookupComboDlg',
    'TwwDBRichEdit',
    'TwwDBSpinEdit',
    'TwwIncrementalSearch',
    'TwwRadioButton'
    );

  begin
    if AControl <> nil then
    begin
      for j:=0 to 49 do
      begin
        if AControl.ClassName.ToUpper.ToUpper= ComponentType[j].ToUpper then
        begin
          with D2Bridge.Items.Add do
          begin
            if AControl.ClassName.ToUpper=UpperCase('TMainMenu') then
              SideMenu(TMainMenu(AControl))
            else
              VCLObj(AControl);
          end;
          Break;
        end;
      end;
      for i := 0 to AControl.ComponentCount - 1 do
        AddControls(AControl.Components[i]);
    end;
  end;
begin
  inherited;
  AddControls(self);
end;
{$endif}
复制代码

 

posted on   秋·风  阅读(482)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示