https://wiki.freepascal.org/api.php?action=feedcontributions&user=007&feedformat=atomFree Pascal wiki - User contributions [en]2024-03-28T09:57:58ZUser contributionsMediaWiki 1.35.6https://wiki.freepascal.org/index.php?title=File:Lazpaint_curve_redim.png&diff=158328File:Lazpaint curve redim.png2024-02-29T23:15:38Z<p>007: 007 uploaded a new version of File:Lazpaint curve redim.png</p>
<hr />
<div>Dessin de courbes et redimensionnement avec LazPaint</div>007https://wiki.freepascal.org/index.php?title=Lazarus_Custom_Drawn_Controls&diff=158215Lazarus Custom Drawn Controls2024-02-08T20:23:05Z<p>007: /* dsWindows7 */</p>
<hr />
<div>{{Lazarus Custom Drawn Controls}}<br />
<br />
The '''Lazarus Custom Drawn Controls''' are a set of controls equivalent to the standard Lazarus controls, but which draw themselves. They can have many uses, including the ability to fully customize the drawing, the ability to have exactly the same look in different platforms and also a higher consistency of behavior.<br />
<br />
This set of controls is divided into two parts:<br />
* the custom drawn controls which are necessary for implementing Lazarus widgetsets and are located in the unit lazarus/lcl/customdrawncontrols.pas. These are described here.<br />
* all other custom drawn controls, which are used often, but aren't indispensable to implement a LCL custom drawn widgetset. Those are located in the package lazarus/components/customdrawn. These are described in the page [[Lazarus Custom Drawn Package]]<br />
<br />
__TOC__<br />
<br />
==How start using these components?==<br />
<br />
To be able to use them in the Lazarus GUI designer install the package lazarus/components/customdrawn.lpk<br />
<br />
To only create customdrawn components by code one can simply add customdrawncontrols, customdrawndrawers and customdrawn_common to the uses clause, declare them and use them. Note that currently only the Win2000 drawer is in the LCL, so any other drawers need to be obtained from the package customdrawn.lpk<br />
<br />
It is important to note that styles are only available if you add the corresponding unit of the style to the uses clause.<br />
<br />
==How do these components work?==<br />
<br />
The basic programming technique utilized by this set of controls is explained at the [[Developing with Graphics#Create a custom control which draws itself]] page.<br />
<br />
The code of the controls itself is implemented in the unit customdrawncontrols.pas, but this unit has no drawing code at all. Customdrawncontrols.pas provides the code which processes all the control's keyboard and mouse events, implementing all the mouse and key response behaviour. Each control instance has a Drawer connected to it. A Drawer in our nomenclature (an instance of the TCDDrawer class) is similar to a theme rendering engine or suchlike. The unit customdrawndrawers.pas manages the list of all known drawers and it also declares all the basic data types needed for State and StateEx. These properties contain all the information about the control's current state, which is passed to the drawer so that it can have the information it requires to draw the control correctly.<br />
Only one instance of each drawer can exist in a program, and all controls refer to that single instance through the drawer's manager in customdrawndrawers.pas. Each control has a property called DrawStyle which allows you to choose (from an enumerated type) which draw style to use, and then customdrawndrawers.pas converts this information into a Drawer instance. You can specify the dsDefault DrawStyle which will then use the style specified in the global variable DefaultStyle. This was done to allow the style of all controls to be changed at once. Simply change this global variable and then call Invalidate on the controls. You can see below a code snippet from customdrawndrawers.pas which shows the methods which have been exposed to manage the list of drawers and also the Default style:<br />
<br />
<syntaxhighlight lang=pascal><br />
unit customdrawndrawers;<br />
//...<br />
TCDDrawStyle = (<br />
// The default is given by the DefaultStyle global variable<br />
// Don't implement anything for this drawer<br />
dsDefault = 0,<br />
// This is a common drawer, the base for all others. It implements the look from dsWin2000<br />
dsCommon,<br />
// Operating system styles<br />
dsWinCE, dsWin2000, dsWinXP,<br />
dsKDEPlastique, dsGNOME, dsMacOSX,<br />
dsAndroid,<br />
// Other special styles for the user<br />
dsExtra1, dsExtra2, dsExtra3, dsExtra4, dsExtra5,<br />
dsExtra6, dsExtra7, dsExtra8, dsExtra9, dsExtra10<br />
);<br />
//...<br />
procedure RegisterDrawer(ADrawer: TCDDrawer; AStyle: TCDDrawStyle);<br />
function GetDefaultDrawer: TCDDrawer;<br />
function GetDrawer(AStyle: TCDDrawStyle): TCDDrawer;<br />
<br />
var<br />
DefaultStyle: TCDDrawStyle = dsCommon; // For now default to the most complete one, later per platform<br />
</syntaxhighlight><br />
<br />
Each Drawer class has methods to draw all controls and also all available primitives. All new drawers created by users should inherit from the class TCDCommonDrawer (which is the basic common drawer declared in the unit customdrawn_common.pas). If you don't inherit from TCDCommonDrawer your application might crash if it hits an abstract method. This is the most complete drawer, which implements all abstract methods from its base class, so inheriting from it guarantees that there will never be crashes owing to methods you have not yet implemented. Other drawers can override the desired methods to change the drawing style.<br />
<br />
The dsCommon drawer uses only TCanvas for all its rendering, but other themes might also use TLazIntfImage and TFPImageCanvas instead, in order to have a faster pixel access. This programming technique is described in [[Developing with Graphics#Working with TLazIntfImage]].<br />
<br />
===Color Palette===<br />
<br />
Drawers have also access to a color Palette, which has the usual LCL system colors. Default drawers will load their colors from the operating system via the LCL acording to the native platform. However, outside their native platform, drawers will use a standard color palette.<br />
<br />
<syntaxhighlight lang=pascal><br />
TCDColorPalette = class<br />
public<br />
ScrollBar, Background, ActiveCaption, InactiveCaption,<br />
Menu, Window, WindowFrame, MenuText, WindowText, CaptionText,<br />
ActiveBorder, InactiveBorder, AppWorkspace, Highlight, HighlightText,<br />
BtnFace, BtnShadow, GrayText, BtnText, InactiveCaptionText,<br />
BtnHighlight, color3DDkShadow, color3DLight, InfoText, InfoBk,<br />
//<br />
HotLight, GradientActiveCaption, GradientInactiveCaption,<br />
MenuHighlight, MenuBar, Form: TColor;<br />
end;<br />
<br />
{ There are 5 possible sources of input for color palettes:<br />
palDefault - Uses palNative when the operating system matches the drawer style,<br />
palFallback otherwise<br />
palNative - Obtain from the operating system<br />
palFallback - Use the fallback colors of the drawer<br />
palUserConfig-Load it from the user configuration files, ToDo<br />
palCustom - The user application has set its own palette<br />
}<br />
TCDPaletteKind = (palDefault, palNative, palFallback, palUserConfig, palCustom);<br />
<br />
{ TCDDrawer }<br />
<br />
TCDDrawer = class<br />
protected<br />
public<br />
Palette: TCDColorPalette;<br />
constructor Create; virtual;<br />
destructor Destroy; override;<br />
procedure SetPaletteKind(APaletteKind: TCDPaletteKind);<br />
procedure LoadNativePaletteColors;<br />
procedure LoadFallbackPaletteColors; virtual;<br />
</syntaxhighlight><br />
<br />
As the code above shows, you can choose where the colors should come from - either from the operating system current theme, from the drawer's default, or from a user-defined scheme provided by your application. This allows you to change all yor application's colors at runtime simply by changing the palette.<br />
<br />
==The Drawers==<br />
<br />
===dsCommon===<br />
<br />
This is the base drawer for all others and it implements a Win2000-look with some small improvements, like better focus drawings on controls<br />
<br />
===dsWinCE===<br />
<br />
Imitates the Windows CE look, with some small improvements like better focus drawings on controls<br />
<br />
===dsWin2000===<br />
<br />
Imitates the Windows 2000 look. Since dsCommon provides the Windows 2000 look already, this class implements no methods at all<br />
<br />
===dsWinXP===<br />
<br />
Imitates the Windows XP look<br />
<br />
===dsKDEPlastique===<br />
<br />
Imitates the look of the Plastique Qt/KDE Theme<br />
<br />
===dsAndroid===<br />
<br />
Imitates the Android look<br />
<br />
===dsWindows7===<br />
<br />
[[File:customdrawn_windowsxp.png]]<br />
[[File:customdrawn_windows7.png]]<br />
[[File:customdrawn_windows8.png]]<br />
[[File:customdrawn_windows11.png]]<br />
[[File:customdrawn_3d.png]]<br />
<br />
<br />
Imitates the Windows look. Currently is available only with BGRABitmap graphic library, and you can get this drawer in the BGRAControls package: [[BGRAControls]]<br />
<br />
===BGRAControls Custom Drawn default style===<br />
<br />
[[File:customdrawn_dark.png]]<br />
<br />
==Controls which imitate the Standard Palette==<br />
<br />
===TCDButton===<br />
<br />
This is a fully custom drawn button.<br />
<br />
Usage example:<br />
<br />
<syntaxhighlight lang=pascal><br />
uses customdrawnextras;<br />
<br />
procedure TForm1.FormCreate(Sender: TObject);<br />
var<br />
MyButton: TCDButton;<br />
begin<br />
MyButton := TCDButton.Create(Self);<br />
MyButton.Parent := Self;<br />
MyButton.DrawStyle := dsWin2000;<br />
MyButton.Left := 100;<br />
MyButton.Top := 100;<br />
MyButton.Width := 200;<br />
MyButton.Height := 50;<br />
MyButton.Caption := 'My Button';<br />
MyButton.Color := clRed;<br />
MyButton.OnClick := @HandleButtonClick;<br />
end;<br />
</syntaxhighlight><br />
<br />
[[Image:Custom_drawn_buttons.png]]<br />
<br />
===TCDEdit===<br />
<br />
This is a fully custom drawn edit control.<br />
<br />
[[Image:TCDEdit.png]]<br />
<br />
===TCDCheckBox===<br />
<br />
This is a fully custom drawn check box.<br />
<br />
[[Image:TCDCheckBox.png]]<br />
<br />
===TCDRadioButton===<br />
<br />
[[Image:TCDRadioButton.png]]<br />
<br />
===TCDScrollBar===<br />
<br />
[[Image:TCDScrollBar.png]]<br />
<br />
===TCDGroupBox===<br />
<br />
This is a fully custom drawn group box.<br />
<br />
[[Image:TCDGroupBox.png]]<br />
<br />
==Controls which imitate the Additional Palette==<br />
<br />
===TCDStaticText===<br />
<br />
==Controls which imitate the Common Controls Palette==<br />
<br />
===TCDTrackBar===<br />
<br />
A substitute for TTrackBar<br />
<br />
[[Image:TCDTrackBar.png]]<br />
<br />
===TCDProgressBar===<br />
<br />
[[Image:TCDProgressBar.png]]<br />
<br />
===TCDListView===<br />
<br />
Under construction.<br />
<br />
===TCDTabControl===<br />
<br />
A substitute for TTabControl<br />
<br />
===TCDPageControl===<br />
<br />
A substitute for TPageControl<br />
<br />
[[Image:TCDPageControl.png]]<br />
<br />
==Custom Drawn Packages==<br />
<br />
Moved here: [[Lazarus Custom Drawn Package]]<br />
<br />
==Other good custom drawn components for Lazarus==<br />
<br />
* [[VirtualTreeview]]<br />
* [[ATTabs]]<br />
* [[ATStatusBar]]<br />
* [[ATScrollBar]]<br />
<br />
==Maintainers==<br />
<br />
* [[User:Sekelsenmat|Felipe Monteiro de Carvalho]]<br />
* JiXian Yang<br />
<br />
== See Also ==<br />
<br />
*[[Lazarus Components Directory]]<br />
*[[Lazarus Custom Drawn Package]]<br />
*[[Custom Drawn Interface]]</div>007https://wiki.freepascal.org/index.php?title=File:customdrawn_dark.png&diff=158214File:customdrawn dark.png2024-02-08T20:22:58Z<p>007: </p>
<hr />
<div></div>007https://wiki.freepascal.org/index.php?title=Lazarus_Custom_Drawn_Controls&diff=158213Lazarus Custom Drawn Controls2024-02-08T20:21:13Z<p>007: /* dsWindows7 */</p>
<hr />
<div>{{Lazarus Custom Drawn Controls}}<br />
<br />
The '''Lazarus Custom Drawn Controls''' are a set of controls equivalent to the standard Lazarus controls, but which draw themselves. They can have many uses, including the ability to fully customize the drawing, the ability to have exactly the same look in different platforms and also a higher consistency of behavior.<br />
<br />
This set of controls is divided into two parts:<br />
* the custom drawn controls which are necessary for implementing Lazarus widgetsets and are located in the unit lazarus/lcl/customdrawncontrols.pas. These are described here.<br />
* all other custom drawn controls, which are used often, but aren't indispensable to implement a LCL custom drawn widgetset. Those are located in the package lazarus/components/customdrawn. These are described in the page [[Lazarus Custom Drawn Package]]<br />
<br />
__TOC__<br />
<br />
==How start using these components?==<br />
<br />
To be able to use them in the Lazarus GUI designer install the package lazarus/components/customdrawn.lpk<br />
<br />
To only create customdrawn components by code one can simply add customdrawncontrols, customdrawndrawers and customdrawn_common to the uses clause, declare them and use them. Note that currently only the Win2000 drawer is in the LCL, so any other drawers need to be obtained from the package customdrawn.lpk<br />
<br />
It is important to note that styles are only available if you add the corresponding unit of the style to the uses clause.<br />
<br />
==How do these components work?==<br />
<br />
The basic programming technique utilized by this set of controls is explained at the [[Developing with Graphics#Create a custom control which draws itself]] page.<br />
<br />
The code of the controls itself is implemented in the unit customdrawncontrols.pas, but this unit has no drawing code at all. Customdrawncontrols.pas provides the code which processes all the control's keyboard and mouse events, implementing all the mouse and key response behaviour. Each control instance has a Drawer connected to it. A Drawer in our nomenclature (an instance of the TCDDrawer class) is similar to a theme rendering engine or suchlike. The unit customdrawndrawers.pas manages the list of all known drawers and it also declares all the basic data types needed for State and StateEx. These properties contain all the information about the control's current state, which is passed to the drawer so that it can have the information it requires to draw the control correctly.<br />
Only one instance of each drawer can exist in a program, and all controls refer to that single instance through the drawer's manager in customdrawndrawers.pas. Each control has a property called DrawStyle which allows you to choose (from an enumerated type) which draw style to use, and then customdrawndrawers.pas converts this information into a Drawer instance. You can specify the dsDefault DrawStyle which will then use the style specified in the global variable DefaultStyle. This was done to allow the style of all controls to be changed at once. Simply change this global variable and then call Invalidate on the controls. You can see below a code snippet from customdrawndrawers.pas which shows the methods which have been exposed to manage the list of drawers and also the Default style:<br />
<br />
<syntaxhighlight lang=pascal><br />
unit customdrawndrawers;<br />
//...<br />
TCDDrawStyle = (<br />
// The default is given by the DefaultStyle global variable<br />
// Don't implement anything for this drawer<br />
dsDefault = 0,<br />
// This is a common drawer, the base for all others. It implements the look from dsWin2000<br />
dsCommon,<br />
// Operating system styles<br />
dsWinCE, dsWin2000, dsWinXP,<br />
dsKDEPlastique, dsGNOME, dsMacOSX,<br />
dsAndroid,<br />
// Other special styles for the user<br />
dsExtra1, dsExtra2, dsExtra3, dsExtra4, dsExtra5,<br />
dsExtra6, dsExtra7, dsExtra8, dsExtra9, dsExtra10<br />
);<br />
//...<br />
procedure RegisterDrawer(ADrawer: TCDDrawer; AStyle: TCDDrawStyle);<br />
function GetDefaultDrawer: TCDDrawer;<br />
function GetDrawer(AStyle: TCDDrawStyle): TCDDrawer;<br />
<br />
var<br />
DefaultStyle: TCDDrawStyle = dsCommon; // For now default to the most complete one, later per platform<br />
</syntaxhighlight><br />
<br />
Each Drawer class has methods to draw all controls and also all available primitives. All new drawers created by users should inherit from the class TCDCommonDrawer (which is the basic common drawer declared in the unit customdrawn_common.pas). If you don't inherit from TCDCommonDrawer your application might crash if it hits an abstract method. This is the most complete drawer, which implements all abstract methods from its base class, so inheriting from it guarantees that there will never be crashes owing to methods you have not yet implemented. Other drawers can override the desired methods to change the drawing style.<br />
<br />
The dsCommon drawer uses only TCanvas for all its rendering, but other themes might also use TLazIntfImage and TFPImageCanvas instead, in order to have a faster pixel access. This programming technique is described in [[Developing with Graphics#Working with TLazIntfImage]].<br />
<br />
===Color Palette===<br />
<br />
Drawers have also access to a color Palette, which has the usual LCL system colors. Default drawers will load their colors from the operating system via the LCL acording to the native platform. However, outside their native platform, drawers will use a standard color palette.<br />
<br />
<syntaxhighlight lang=pascal><br />
TCDColorPalette = class<br />
public<br />
ScrollBar, Background, ActiveCaption, InactiveCaption,<br />
Menu, Window, WindowFrame, MenuText, WindowText, CaptionText,<br />
ActiveBorder, InactiveBorder, AppWorkspace, Highlight, HighlightText,<br />
BtnFace, BtnShadow, GrayText, BtnText, InactiveCaptionText,<br />
BtnHighlight, color3DDkShadow, color3DLight, InfoText, InfoBk,<br />
//<br />
HotLight, GradientActiveCaption, GradientInactiveCaption,<br />
MenuHighlight, MenuBar, Form: TColor;<br />
end;<br />
<br />
{ There are 5 possible sources of input for color palettes:<br />
palDefault - Uses palNative when the operating system matches the drawer style,<br />
palFallback otherwise<br />
palNative - Obtain from the operating system<br />
palFallback - Use the fallback colors of the drawer<br />
palUserConfig-Load it from the user configuration files, ToDo<br />
palCustom - The user application has set its own palette<br />
}<br />
TCDPaletteKind = (palDefault, palNative, palFallback, palUserConfig, palCustom);<br />
<br />
{ TCDDrawer }<br />
<br />
TCDDrawer = class<br />
protected<br />
public<br />
Palette: TCDColorPalette;<br />
constructor Create; virtual;<br />
destructor Destroy; override;<br />
procedure SetPaletteKind(APaletteKind: TCDPaletteKind);<br />
procedure LoadNativePaletteColors;<br />
procedure LoadFallbackPaletteColors; virtual;<br />
</syntaxhighlight><br />
<br />
As the code above shows, you can choose where the colors should come from - either from the operating system current theme, from the drawer's default, or from a user-defined scheme provided by your application. This allows you to change all yor application's colors at runtime simply by changing the palette.<br />
<br />
==The Drawers==<br />
<br />
===dsCommon===<br />
<br />
This is the base drawer for all others and it implements a Win2000-look with some small improvements, like better focus drawings on controls<br />
<br />
===dsWinCE===<br />
<br />
Imitates the Windows CE look, with some small improvements like better focus drawings on controls<br />
<br />
===dsWin2000===<br />
<br />
Imitates the Windows 2000 look. Since dsCommon provides the Windows 2000 look already, this class implements no methods at all<br />
<br />
===dsWinXP===<br />
<br />
Imitates the Windows XP look<br />
<br />
===dsKDEPlastique===<br />
<br />
Imitates the look of the Plastique Qt/KDE Theme<br />
<br />
===dsAndroid===<br />
<br />
Imitates the Android look<br />
<br />
===dsWindows7===<br />
<br />
[[File:customdrawn_windowsxp.png]]<br />
[[File:customdrawn_windows7.png]]<br />
[[File:customdrawn_windows8.png]]<br />
[[File:customdrawn_windows11.png]]<br />
[[File:customdrawn_3d.png]]<br />
<br />
<br />
Imitates the Windows look. Currently is available only with BGRABitmap graphic library, and you can get this drawer in the BGRAControls package: [[BGRAControls]]<br />
<br />
==Controls which imitate the Standard Palette==<br />
<br />
===TCDButton===<br />
<br />
This is a fully custom drawn button.<br />
<br />
Usage example:<br />
<br />
<syntaxhighlight lang=pascal><br />
uses customdrawnextras;<br />
<br />
procedure TForm1.FormCreate(Sender: TObject);<br />
var<br />
MyButton: TCDButton;<br />
begin<br />
MyButton := TCDButton.Create(Self);<br />
MyButton.Parent := Self;<br />
MyButton.DrawStyle := dsWin2000;<br />
MyButton.Left := 100;<br />
MyButton.Top := 100;<br />
MyButton.Width := 200;<br />
MyButton.Height := 50;<br />
MyButton.Caption := 'My Button';<br />
MyButton.Color := clRed;<br />
MyButton.OnClick := @HandleButtonClick;<br />
end;<br />
</syntaxhighlight><br />
<br />
[[Image:Custom_drawn_buttons.png]]<br />
<br />
===TCDEdit===<br />
<br />
This is a fully custom drawn edit control.<br />
<br />
[[Image:TCDEdit.png]]<br />
<br />
===TCDCheckBox===<br />
<br />
This is a fully custom drawn check box.<br />
<br />
[[Image:TCDCheckBox.png]]<br />
<br />
===TCDRadioButton===<br />
<br />
[[Image:TCDRadioButton.png]]<br />
<br />
===TCDScrollBar===<br />
<br />
[[Image:TCDScrollBar.png]]<br />
<br />
===TCDGroupBox===<br />
<br />
This is a fully custom drawn group box.<br />
<br />
[[Image:TCDGroupBox.png]]<br />
<br />
==Controls which imitate the Additional Palette==<br />
<br />
===TCDStaticText===<br />
<br />
==Controls which imitate the Common Controls Palette==<br />
<br />
===TCDTrackBar===<br />
<br />
A substitute for TTrackBar<br />
<br />
[[Image:TCDTrackBar.png]]<br />
<br />
===TCDProgressBar===<br />
<br />
[[Image:TCDProgressBar.png]]<br />
<br />
===TCDListView===<br />
<br />
Under construction.<br />
<br />
===TCDTabControl===<br />
<br />
A substitute for TTabControl<br />
<br />
===TCDPageControl===<br />
<br />
A substitute for TPageControl<br />
<br />
[[Image:TCDPageControl.png]]<br />
<br />
==Custom Drawn Packages==<br />
<br />
Moved here: [[Lazarus Custom Drawn Package]]<br />
<br />
==Other good custom drawn components for Lazarus==<br />
<br />
* [[VirtualTreeview]]<br />
* [[ATTabs]]<br />
* [[ATStatusBar]]<br />
* [[ATScrollBar]]<br />
<br />
==Maintainers==<br />
<br />
* [[User:Sekelsenmat|Felipe Monteiro de Carvalho]]<br />
* JiXian Yang<br />
<br />
== See Also ==<br />
<br />
*[[Lazarus Components Directory]]<br />
*[[Lazarus Custom Drawn Package]]<br />
*[[Custom Drawn Interface]]</div>007https://wiki.freepascal.org/index.php?title=File:customdrawn_windows7.png&diff=158212File:customdrawn windows7.png2024-02-08T20:20:49Z<p>007: </p>
<hr />
<div></div>007https://wiki.freepascal.org/index.php?title=File:customdrawn_3d.png&diff=158211File:customdrawn 3d.png2024-02-08T20:20:05Z<p>007: </p>
<hr />
<div></div>007https://wiki.freepascal.org/index.php?title=File:customdrawn_windows11.png&diff=158210File:customdrawn windows11.png2024-02-08T20:19:57Z<p>007: </p>
<hr />
<div></div>007https://wiki.freepascal.org/index.php?title=File:customdrawn_windows8.png&diff=158209File:customdrawn windows8.png2024-02-08T20:19:47Z<p>007: </p>
<hr />
<div></div>007https://wiki.freepascal.org/index.php?title=File:customdrawn_windowsxp.png&diff=158208File:customdrawn windowsxp.png2024-02-08T20:19:39Z<p>007: </p>
<hr />
<div></div>007https://wiki.freepascal.org/index.php?title=Translations_/_i18n_/_localizations_for_programs&diff=142232Translations / i18n / localizations for programs2021-01-09T03:33:48Z<p>007: /* Quick i18n */</p>
<hr />
<div>{{Translations_/_i18n_/_localizations_for_programs}}<br />
<br />
This is about how a program can use different strings for various languages like English, Chinese, German, Finnish, Italian and any other language.<br />
<br />
* '''i18n''' is short for '''internationalization''' (18 being the number of characters between i and n of the word internationalization)<br />
* '''l10n''' is short for '''localization''' (10 being the number of characters between l and n of the word localization)<br />
<br />
<br />
==Quick i18n==<br />
<br />
This is intended as be a quick guide to introduce yourself in the world of translations and get things done quickly. Check also [[Language Codes]] and [[BidiMode]].<br />
<br />
For your information the most used languages in the world ([http://www.redlinels.com/2014/01/10/most-widely-spoken-languages/ source]) are:<br />
<br />
* 1 - Chinese: With more than 1.2 billion native speakers in the world<br />
* 2 - Spanish: Spanish occupies the No. 2 spot and is spoken in approximately 30 countries.<br />
* 3 - English: 335 million worldwide—about 5% of the world’s population. (This does not takes into account second language spoken).<br />
* 4 - Hindi: Spoken by over 260 million people.<br />
* 5 - Arabic: Spoken in almost 60 countries around the world.<br />
* 6 - Portuguese: Population of Brazil is over 200 million. The population of Portugal is just over 10 million.<br />
* 7 - Bengali: The main language of Bangladesh (population, 155 million) and one of India’s many official languages.<br />
* 8 - Russian and Japanese.<br />
<br />
===poedit===<br />
<br />
The best known tool is a program called [https://poedit.net/ poedit]. poedit is a tool for translators. It produces both PO and MO as output.<br />
<br />
===Translating Forms===<br />
<br />
When you save a form with the i18n options enabled, it generates a file .lrj, that file is used to create the final .po file. So is very important that you include that file with your source code in the version system you're using, don't add that file to ignored (say .gitignore), else your translations will be broken.<br />
<br />
===Translating Resourcestrings===<br />
<br />
This is the way to store a resourcestring in a unit:<br />
<br />
<syntaxhighlight lang="pascal"><br />
resourcestring<br />
Caption1 = 'Some text';<br />
HelloWorld1 = 'Hello World';<br />
</syntaxhighlight><br />
<br />
Resourcestrings are like normal string constants, that means you can assign them to any string:<br />
<br />
<syntaxhighlight lang="pascal">Label1.Caption := HelloWorld1;</syntaxhighlight><br />
<br />
===Compiling into .po files===<br />
<br />
Resourcestrings are compiled into .po files if you enable i18n in the Lazarus IDE. Go to Project > Project Options > i18n > Enable i18n. When you recompile your application the .po files will be updated. You may also select a directory where .po files will be stored, recommended '''po_files'''.<br />
<br />
The default translation is recommended to be in English or the default language of your application, since it will be loaded if no other translation file is found.<br />
<br />
When you have your '''project1.po''' copy and paste it and rename it to '''project1.es.po''' or one of the [[Language Codes]] of your choice. Then you will have 2 languages: English and Spanish. Then you must send to the translator the files for translation.<br />
<br />
Your folder structure will look something like this:<br />
<br />
<syntaxhighlight lang="text"><br />
project1\po_files\<br />
project1\po_files\project1.po<br />
project1\po_files\project1.es.po<br />
</syntaxhighlight><br />
<br />
===Converting .po files to .mo files===<br />
<br />
When you have the translation finished in the .po file, you want to compile it to .mo to load it faster since is a binary format. To convert to .mo you can use poedit and go to File > Compile as .mo.<br />
<br />
Note that [[Everything else about translations]] has a section about where a Lazarus app looks for its language files.<br />
<br />
===Automatic translation===<br />
<br />
When you have the .mo files ready, put them in the '''locale''' or '''languages''' folder right to your application executable, then include the unit '''DefaultTranslator''' and that's all. The translation will be done automatically.<br />
<br />
<syntaxhighlight lang="pascal"><br />
uses<br />
DefaultTranslator;<br />
</syntaxhighlight><br />
<br />
You want to distribute only the .mo files in the '''locale''' or '''languages''' directory, since .po files are usefull only for making the translation and compiling them into a .mo file.<br />
<br />
Your folder structure will look something like this:<br />
<br />
<syntaxhighlight lang="text"><br />
project1\project1.exe<br />
project1\locale\<br />
project1\locale\project1.mo<br />
project1\locale\project1.es.mo<br />
</syntaxhighlight><br />
<br />
===Testing translations===<br />
<br />
When you have everything ready. you want to test if the translations looks fine in your application for each language you have. Automatic translation has a feature that you can use in order to test each language quickly.<br />
<br />
You must run your executable with the command line parameter '''--lang''' followed by the language code of your choice.<br />
<br />
You will run your executable like this in order to test Spanish translation:<br />
<br />
<syntaxhighlight lang="text"><br />
project1.exe --lang es<br />
</syntaxhighlight><br />
<br />
And you will see the translated application.<br />
<br />
You can do this with the IDE. Go to '''Run > Run Parameters ...'''. In that window in the input '''Command line parameters (without application name)''' write this:<br />
<br />
<syntaxhighlight lang="text"><br />
--lang it<br />
</syntaxhighlight><br />
<br />
Then '''Run (F9)''' and you will see the translated application.<br />
<br />
===Final steps===<br />
<br />
These steps are to get a better result for your entire translation.<br />
<br />
====Translate LCL====<br />
<br />
To get everything translated you must include the LCL translations into your application '''locale''' folder.<br />
<br />
Copy everything inside the folder '''C:\lazarus\lcl\languages''' to your '''locale''' folder. Then you will have the LCL translated for your application.<br />
<br />
====Format Settings====<br />
<br />
For Windows you must read [[Step-by-step instructions for creating multi-language applications#Format settings]] to get format settings in the right place.<br />
<br />
Under Linux, BSD and macOS there are several locales defining things like time and date format or the thousands separator. In order to initialize the RTL you need to include the '''clocale''' unit in the uses section of your program (.lpr file).<br />
<br />
====BiDiMode====<br />
<br />
[[BidiMode]] is for languages like Arabic that read and write right to left. See also [http://www.w3.org/International/questions/qa-scripts.en Script direction and languages] for a list of LTR (Left To Right) and RTL (Right To Left) languages and most used languages in general.<br />
<br />
With this unit you can determine what BiDiMode is right for you. This code is tested in Lazarus Trunk and may or not work in current release (see the changes on this page to get the old source).<br />
<br />
First save this unit as ubidimodetools.pas:<br />
<br />
<syntaxhighlight lang="pascal"><br />
unit ubidimodetools;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Classes, SysUtils;<br />
<br />
function GetLang: string;<br />
function GetBiDiMode: TBiDiMode;<br />
<br />
implementation<br />
<br />
uses<br />
FileUtil, LCLProc, LazUTF8;<br />
<br />
function GetLang: string;<br />
var<br />
T: string; // unused FallBackLang<br />
i: integer;<br />
begin<br />
Result := '';<br />
{ We use the same method that is used in LCLTranslator unit }<br />
<br />
for i := 1 to Paramcount - 1 do<br />
if (ParamStrUTF8(i) = '--LANG') or (ParamStrUTF8(i) = '-l') or<br />
(ParamStrUTF8(i) = '--lang') then<br />
Result := ParamStrUTF8(i + 1);<br />
<br />
//Win32 user may decide to override locale with LANG variable.<br />
if Result = '' then<br />
Result := GetEnvironmentVariableUTF8('LANG');<br />
<br />
if Result = '' then<br />
LazGetLanguageIDs(Result, {%H-}T);<br />
end;<br />
<br />
function GetBiDiMode: TBiDiMode;<br />
begin<br />
case GetLang of<br />
// Arabic<br />
'ar': Result := bdRightToLeft;<br />
else<br />
Result := bdLeftToRight;<br />
end;<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
When you create a form do this:<br />
<br />
<syntaxhighlight lang="pascal"><br />
BiDiMode := GetBiDiMode;<br />
</syntaxhighlight><br />
<br />
'''Note:''' You must be sure that you have the proper translations in order to get it working.<br />
<br />
'''Note 2:''' Maybe this is not neccesary at all since Windows can change the BiDiMode automatically.<br />
<br />
===Technical Details===<br />
<br />
====gettext====<br />
<br />
The main technology involved in the process of translations is [https://www.gnu.org/software/gettext/manual/gettext.html GNU gettext]. FPC comes with the gettext unit.<br />
<br />
<syntaxhighlight lang="pascal"><br />
uses<br />
gettext;<br />
</syntaxhighlight><br />
<br />
====PO====<br />
<br />
PO – Portable Object. This is the file that you receive back from the translators. It’s a text file that includes the original text and the translations.<br />
<br />
====MO====<br />
<br />
MO – Machine Object. The MO file includes the exact same contents as the PO file. The two files differ in their format. While a PO file is a text file and is easy for humans to read, MO files are compiled and are easy for computers to read. The unit gettext implements TMOFile and has several procedures to do the translation from .mo files, if you want to use it.<br />
<br />
<syntaxhighlight lang="pascal"><br />
unit gettext;<br />
<br />
...<br />
<br />
TMOFile = class<br />
<br />
...<br />
<br />
procedure GetLanguageIDs(var Lang, FallbackLang: string);<br />
procedure TranslateResourceStrings(AFile: TMOFile);<br />
procedure TranslateUnitResourceStrings(const AUnitName:string; AFile: TMOFile);<br />
procedure TranslateResourceStrings(const AFilename: String);<br />
procedure TranslateUnitResourceStrings(const AUnitName:string; const AFilename: String);<br />
</syntaxhighlight><br />
<br />
==Everything else about translations==<br />
<br />
Here is all the translation material that was here in the past. There are a lot of articles about translations that can cause trouble to novices. To keep it simple this other material has been moved to: [[Everything else about translations]]. Please keep this article as clean as possible.<br />
<br />
==See also==<br />
<br />
* [[IDE_Development#Translations.2C_i18n.2C_lrt_files.2C_po_files|IDE Development: Translations, i18n, lrt, po files]]<br />
* [[Getting_translation_strings_right|Getting translation strings right]]<br />
* [[Lazarus_Documentation#Translating.2FInternationalization.2FLocalization|Translating/Internationalization/Localization]]<br />
* [[Step-by-step_instructions_for_creating_multi-language_applications|Step-by-step instructions for creating multi-language applications]]<br />
<br />
[[Category:Tutorials]]<br />
[[Category:Localization]]</div>007https://wiki.freepascal.org/index.php?title=SVG_Image_List&diff=141529SVG Image List2020-12-13T15:56:08Z<p>007: /* Create SVG Image List */</p>
<hr />
<div>Hi, this is a simple tutorial on how to use SVG Images in our Lazarus applications.<br />
<br />
== Requirements ==<br />
<br />
1) Install [[BGRABitmap]]<br />
<br />
2) Install [[BGRAControls]]<br />
<br />
(Hint: Use online package manager)<br />
<br />
== Tutorial ==<br />
<br />
In this tutorial we will add an SVG Icon to a TMainMenu.<br />
<br />
=== Create elements ===<br />
<br />
1) Drop a TMainMenu, add some entries like 'File' and a sub entry 'Open'.<br />
<br />
2) Drop a regular TImageList, assign it to the MainMenu1 we previously created.<br />
<br />
3) Assign the ImageIndex in the entries, for example in the File > Open add index 0.<br />
<br />
That is not different as you need to do it anyways with a regular image list, so nothing changes here. The next step shows the SVG stuff.<br />
<br />
=== Create SVG Image List ===<br />
<br />
1) Add a TBGRASVGImageList from BGRA Themes pallete.<br />
<br />
2) Double click the SVG Image List component and add some SVG's, just load them from file.<br />
<br />
3) Add this code, the glue between our two image lists:<br />
<br />
<syntaxhighlight lang="pascal"><br />
procedure TForm1.FormCreate(Sender: TObject);<br />
begin<br />
BGRASVGImageList1.PopulateImageList(ImageList1, [24]);<br />
end; <br />
</syntaxhighlight><br />
<br />
'''Done!'''<br />
<br />
Now you have SVG Icons in your application, repeat for buttons and any component that supports a regular image list.<br />
<br />
=== Optional parameter ===<br />
<br />
The second parameter is array of resolutions, 24px is the default on Windows. You can add more like 48px for retina on macOS or High DPI on Windows.<br />
<br />
<syntaxhighlight lang="pascal"><br />
BGRASVGImageList1.PopulateImageList(ImageList1, [24, 48]);<br />
</syntaxhighlight><br />
<br />
'''Important:''' You need to enable 'Scaled' property on the regular image list in order to the extra resolutions work fine.<br />
<br />
Enjoy!</div>007https://wiki.freepascal.org/index.php?title=SVG_Image_List&diff=141528SVG Image List2020-12-13T15:55:18Z<p>007: Created page with "Hi, this is a simple tutorial on how to use SVG Images in our Lazarus applications. == Requirements == 1) Install BGRABitmap 2) Install BGRAControls (Hint: Use onl..."</p>
<hr />
<div>Hi, this is a simple tutorial on how to use SVG Images in our Lazarus applications.<br />
<br />
== Requirements ==<br />
<br />
1) Install [[BGRABitmap]]<br />
<br />
2) Install [[BGRAControls]]<br />
<br />
(Hint: Use online package manager)<br />
<br />
== Tutorial ==<br />
<br />
In this tutorial we will add an SVG Icon to a TMainMenu.<br />
<br />
=== Create elements ===<br />
<br />
1) Drop a TMainMenu, add some entries like 'File' and a sub entry 'Open'.<br />
<br />
2) Drop a regular TImageList, assign it to the MainMenu1 we previously created.<br />
<br />
3) Assign the ImageIndex in the entries, for example in the File > Open add index 0.<br />
<br />
That is not different as you need to do it anyways with a regular image list, so nothing changes here. The next step shows the SVG stuff.<br />
<br />
=== Create SVG Image List ===<br />
<br />
1) Add a TBGRASVGImageList from BGRA Themes pallete.<br />
<br />
2) Double click the SVG Image List component and add some SVG's, just load them from file.<br />
<br />
3) Add this code, the glue between our two image lists:<br />
<br />
<syntaxhighlight lang="pascal"><br />
procedure TForm1.FormCreate(Sender: TObject);<br />
begin<br />
BGRASVGImageList1.PopulateImageList(ImageList1, [24]);<br />
end; <br />
</syntaxhighlight><br />
<br />
'''Done!'''<br />
<br />
Now you have SVG Icons in your application, repeat for buttons and any component that supports a regular image list.<br />
<br />
Attached a demo.<br />
<br />
=== Optional parameter ===<br />
<br />
The second parameter is array of resolutions, 24px is the default on Windows. You can add more like 48px for retina on macOS or High DPI on Windows.<br />
<br />
<syntaxhighlight lang="pascal"><br />
BGRASVGImageList1.PopulateImageList(ImageList1, [24, 48]);<br />
</syntaxhighlight><br />
<br />
'''Important:''' You need to enable 'Scaled' property on the regular image list in order to the extra resolutions work fine.<br />
<br />
Enjoy!</div>007https://wiki.freepascal.org/index.php?title=BGRABitmap_tutorial&diff=141527BGRABitmap tutorial2020-12-13T15:50:09Z<p>007: /* More */</p>
<hr />
<div>{{BGRABitmap_tutorial}}<br />
<br />
{{BGRABitmap_tutorial_index}}<br />
<br />
Welcome to the index of the tutorials for the [[BGRABitmap|BGRABitmap]] library. You can browse tutorials by number with the bar on the top, or by the following categories:<br />
<br />
=== Install BGRABitmap and draw basic shapes ===<br />
<br />
TBGRABitmap images have drawing functions using floating point coordinates or integer coordinates.<br />
<br />
* [[BGRABitmap tutorial 1|Installing BGRABitmap (No. 1)]]<br />
* [[BGRABitmap tutorial 2|Loading and displaying an image (No. 2)]]<br />
* [[BGRABitmap tutorial 3|Drawing with the mouse (No. 3)]]<br />
* [[BGRABitmap tutorial 6|Line styles (No. 6)]]<br />
* [[BGRABitmap tutorial 7|Splines and Bézier curves (No. 7)]]<br />
* [[BGRABitmap tutorial 12|Text functions (No. 12)]]<br />
* [[BGRABitmap tutorial 13|Integer coordinates and floating point coordinates (No. 13)]]<br />
<br />
=== Textures and scanners ===<br />
<br />
Pixels are a table in memory containing values in the TBGRAPixel format. At this level, we can do various operations:<br />
<br />
* [[BGRABitmap tutorial 4|Direct pixel access with Scanline (No. 4)]]<br />
* [[BGRABitmap tutorial 5|Combining layers of pixels (No. 5)]]<br />
* [[BGRABitmap tutorial 8|Generating textures (No. 8)]]<br />
* [[BGRABitmap tutorial 9|Phong shading using textures (No. 9)]]<br />
* [[BGRABitmap tutorial 10|Texture mapping (No. 10)]]<br />
* [[BGRABitmap tutorial 11|Using scanners to combine transformations (No. 11)]]<br />
<br />
=== Other drawing contexts ===<br />
<br />
It is possible to have other contexts, that provide/allow other basic drawing functions:<br />
<br />
* Standard Canvas (Canvas and CanvasOpacity properties) : avoid using it because of the slowness of conversions of bitmap data<br />
* Canvas with features brought by BGRABitmap (CanvasBGRA property, Brush and Pen have an Opacity property)<br />
** [http://www.youtube.com/watch?v=HGYSLgtYx-U How to convert your application from TCanvas to CanvasBGRA (video)]<br />
* [[BGRABitmap tutorial 14|Drawing with a 2D canvas with affine transformations (No. 14)]]<br />
* [[BGRABitmap tutorial 15|Real 3D rendering (No. 15)]]<br />
* [[BGRABitmap tutorial 16|Using textures with 3D rendering (No. 16)]]<br />
<br />
=== More ===<br />
<br />
You can use BGRABitmap to [[BGRABitmap_tutorial_TAChart|improve TAChart rendering]].<br />
<br />
You can use it as well to display icons with the [[SVG_Image_List|SVG Image List]].<br />
<br />
More classes are available (you need to create them when you need them):<br />
<br />
* TBGRATextEffect, in unit BGRATextFX, allows to prepare the drawing of text line, to add effects like contour and shadow.<br />
* TBGRALayeredBitmap, in unit BGRALayers, allow to create a multi-layered bitmap. Units BGRAPaintNet and BGRAOpenRaster contain implementations to read and write in Paint.NET format (read only) and OpenRaster format (read and write).<br />
* Units BGRAGradientScanner and BGRATransform contain scanners to do various effects.<br />
* Unit BGRAGradients contain procedures to generate gradients and TPhongShading class for Phong shading.<br />
* TBGRACompressableBitmap, in unit BGRACompressableBitmap, allow to store and compress images.<br />
<br />
Other units contient low level functions, and you should not need to use them for a normal usage.<br />
<br />
[[Category:Graphics]]<br />
[[Category:Tutorials]]<br />
[[Category:BGRABitmap]]<br />
[[Category:Lazarus]]</div>007https://wiki.freepascal.org/index.php?title=Aero_Glass&diff=137396Aero Glass2020-06-24T23:53:32Z<p>007: /* Windows 10 */</p>
<hr />
<div>{{Platform only|Windows|Windows|Windows}}<br />
{{Aero Glass}}<br />
<br />
== Aero Glass effect on Lazarus Form ==<br />
<br />
[[Image:aero_glass_lazarus.png]]<br />
<br />
First save the above code to a text file "glass.pas":<br />
<br />
<syntaxhighlight lang=pascal>unit glass;<br />
<br />
{$mode delphi}<br />
//{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Windows, Forms, Graphics;<br />
<br />
type<br />
_MARGINS = packed record<br />
cxLeftWidth : Integer;<br />
cxRightWidth : Integer;<br />
cyTopHeight : Integer;<br />
cyBottomHeight : Integer;<br />
end;<br />
<br />
PMargins = ^_MARGINS;<br />
TMargins = _MARGINS;<br />
<br />
DwmIsCompositionEnabledFunc = function(pfEnabled: PBoolean): HRESULT; stdcall;<br />
DwmExtendFrameIntoClientAreaFunc = function(destWnd: HWND; const pMarInset: PMargins): HRESULT; stdcall;<br />
SetLayeredWindowAttributesFunc = function(destWnd: HWND; cKey: TColor; bAlpha: Byte; dwFlags: DWord): BOOL; stdcall;<br />
<br />
const<br />
WS_EX_LAYERED = $80000;<br />
LWA_COLORKEY = 1;<br />
<br />
procedure GlassForm(frm: TForm; tmpMargins: TMargins; cBlurColorKey: TColor = clFuchsia);<br />
function WindowsAeroGlassCompatible: Boolean;<br />
<br />
implementation<br />
<br />
function WindowsAeroGlassCompatible: Boolean;<br />
var<br />
osVinfo: TOSVERSIONINFO;<br />
begin<br />
ZeroMemory(@osVinfo, SizeOf(osVinfo));<br />
OsVinfo.dwOSVersionInfoSize := SizeOf(TOSVERSIONINFO);<br />
if (<br />
(GetVersionEx(osVInfo) = True) and<br />
(osVinfo.dwPlatformId = VER_PLATFORM_WIN32_NT) and<br />
(osVinfo.dwMajorVersion >= 6)<br />
)<br />
then Result:=True<br />
else Result:=False;<br />
end;<br />
<br />
procedure GlassForm(frm: TForm; tmpMargins: TMargins; cBlurColorKey: TColor = clFuchsia);<br />
var<br />
hDwmDLL: Cardinal;<br />
fDwmIsCompositionEnabled: DwmIsCompositionEnabledFunc;<br />
fDwmExtendFrameIntoClientArea: DwmExtendFrameIntoClientAreaFunc;<br />
fSetLayeredWindowAttributesFunc: SetLayeredWindowAttributesFunc;<br />
bCmpEnable: Boolean;<br />
mgn: TMargins;<br />
begin<br />
{ Continue if Windows version is compatible }<br />
if WindowsAeroGlassCompatible then begin<br />
{ Continue if 'dwmapi' library is loaded }<br />
hDwmDLL := LoadLibrary('dwmapi.dll');<br />
if hDwmDLL <> 0 then begin<br />
{ Get values }<br />
@fDwmIsCompositionEnabled := GetProcAddress(hDwmDLL, 'DwmIsCompositionEnabled');<br />
@fDwmExtendFrameIntoClientArea := GetProcAddress(hDwmDLL, 'DwmExtendFrameIntoClientArea');<br />
@fSetLayeredWindowAttributesFunc := GetProcAddress(GetModulehandle(user32), 'SetLayeredWindowAttributes');<br />
{ Continue if values are <> nil }<br />
if (<br />
(@fDwmIsCompositionEnabled <> nil) and<br />
(@fDwmExtendFrameIntoClientArea <> nil) and<br />
(@fSetLayeredWindowAttributesFunc <> nil)<br />
)<br />
then begin<br />
{ Continue if composition is enabled }<br />
fDwmIsCompositionEnabled(@bCmpEnable);<br />
if bCmpEnable = True then begin<br />
{ Set Form Color same as cBlurColorKey }<br />
frm.Color := cBlurColorKey;<br />
{ ... }<br />
SetWindowLong(frm.Handle, GWL_EXSTYLE, GetWindowLong(frm.Handle, GWL_EXSTYLE) or WS_EX_LAYERED);<br />
{ ... }<br />
fSetLayeredWindowAttributesFunc(frm.Handle, cBlurColorKey, 0, LWA_COLORKEY);<br />
{ Set margins }<br />
ZeroMemory(@mgn, SizeOf(mgn));<br />
mgn.cxLeftWidth := tmpMargins.cxLeftWidth;<br />
mgn.cxRightWidth := tmpMargins.cxRightWidth;<br />
mgn.cyTopHeight := tmpMargins.cyTopHeight;<br />
mgn.cyBottomHeight := tmpMargins.cyBottomHeight;<br />
{ Extend Form }<br />
fDwmExtendFrameIntoClientArea(frm.Handle,@mgn);<br />
end;<br />
end;<br />
{ Free loaded 'dwmapi' library }<br />
FreeLibrary(hDWMDLL);<br />
end;<br />
end;<br />
end;<br />
<br />
end.</syntaxhighlight><br />
<br />
Copy the "glass.pas" file to the main folder of your project:<br />
<br />
MyProject\glass.pas<br />
<br />
In the "uses" section of your project you need to add "glass":<br />
<br />
<syntaxhighlight lang=pascal>unit form1;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs<br />
glass; // This includes GlassForm procedure </syntaxhighlight><br />
<br />
OnActivate event of each form call the procedure in this way:<br />
<br />
<syntaxhighlight lang=pascal>procedure TForm1.FormActivate(Sender: TObject);<br />
var<br />
tmpMargins: TMargins;<br />
begin<br />
{ If all margins are -1 the whole form will be aero glass}<br />
tmpMargins.cxLeftWidth := -1;<br />
tmpMargins.cxRightWidth := -1;<br />
tmpMargins.cyBottomHeight := -1;<br />
tmpMargins.cyTopHeight := -1;<br />
{ FormName ; Margins ; TransparentColor }<br />
GlassForm(Self, tmpMargins, clFuchsia); <br />
end;</syntaxhighlight><br />
<br />
Also you need to enable Themes to use this procedure, go to Options > Project Options > then select "Use Manifest to Enable Themes (Windows)".<br />
<br />
== Windows 10 ==<br />
<br />
[[Image:aeroglasswin10.png]]<br />
<br />
<syntaxhighlight lang=pascal><br />
{<br />
author: vhanla<br />
http://vhanla.codigobit.info<br />
}<br />
unit Unit1;<br />
<br />
interface<br />
<br />
uses<br />
Windows, Messages, SysUtils, Variants, Classes, Graphics,<br />
Controls, Forms, Dialogs, DWMApi, png, IntfGraphics, FPImage, GraphType,<br />
StdCtrls, ExtCtrls, BCButtonFocus, BCLabel, Registry, LMessages, LCLType, LCLIntf;<br />
<br />
type<br />
<br />
{ TForm1 }<br />
<br />
TForm1 = class(TForm)<br />
BCButtonFocus1: TBCButtonFocus;<br />
BCLabel1: TBCLabel;<br />
Image1: TImage;<br />
Image2: TImage;<br />
Panel1: TPanel;<br />
<br />
procedure BCButtonFocus1Click(Sender: TObject);<br />
procedure FormCreate(Sender: TObject);<br />
procedure Button1Click(Sender: TObject);<br />
procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton;<br />
Shift: TShiftState; X, Y: Integer);<br />
private<br />
{ Private declarations }<br />
function TaskbarAccented:boolean;<br />
function TaskbarTranslucent:boolean;<br />
procedure EnableBlur;<br />
procedure AeroGlass;<br />
procedure UpdateColorization;<br />
function GetAccentColor:TColor;<br />
public<br />
{ Public declarations }<br />
end;<br />
<br />
AccentPolicy = packed record<br />
AccentState: Integer;<br />
AccentFlags: Integer;<br />
GradientColor: Integer;<br />
AnimationId: Integer;<br />
end;<br />
<br />
TWinCompAttrData = packed record<br />
attribute: THandle;<br />
pData: Pointer;<br />
dataSize: ULONG;<br />
end;<br />
<br />
<br />
var<br />
Form1: TForm1;<br />
<br />
var<br />
SetWindowCompositionAttribute: function (Wnd: HWND; const AttrData: TWinCompAttrData): BOOL; stdcall = Nil;<br />
implementation<br />
<br />
{$R *.lfm}<br />
<br />
procedure SetAlphaColorPicture(<br />
const Col: TColor;<br />
const Alpha: Integer;<br />
Picture: TPicture;<br />
const _width: Integer;<br />
const _height: Integer<br />
);<br />
var<br />
IM: TLazIntfImage;<br />
x,y: integer;<br />
sl: pByteArray;<br />
I, J, W, H: Integer;<br />
FC: TFPColor;<br />
begin<br />
IM := TLazIntfImage.Create(0, 0, [riqfRGB, riqfAlpha]);<br />
try<br />
IM.SetSize(_width, _height);<br />
for I := 0 to _width - 1 do<br />
begin<br />
for J := 0 to _height - 1 do<br />
begin<br />
FC.red := (128 + I) shl 8;<br />
FC.green := (128 + J) shl 8;<br />
FC.blue := 128 shl 8;<br />
FC.alpha := 128 shl 8; // now works fine<br />
IM.Colors[I, J] := FC;<br />
end;<br />
end;<br />
Picture.Assign(IM);<br />
<br />
<br />
finally<br />
IM.Free;<br />
<br />
end;<br />
end;<br />
<br />
procedure TForm1.Button1Click(Sender: TObject);<br />
begin<br />
Close;<br />
end;<br />
<br />
procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;<br />
Shift: TShiftState; X, Y: Integer);<br />
begin<br />
ReleaseCapture;<br />
SendMessage(Form1.Handle, LM_SYSCOMMAND, 61458, 0) ;<br />
end;<br />
<br />
procedure TForm1.AeroGlass;<br />
var<br />
Aero: BOOL;<br />
Area: TRect;<br />
hDWM: THandle;<br />
begin<br />
hDWM:=LoadLibrary('dwmapi.dll');<br />
try<br />
@DwmIsCompositionEnabled:=GetProcAddress(hDWM,'DwmIsCompositionEnabled');<br />
if @DwmIsCompositionEnabled<>nil then<br />
DwmIsCompositionEnabled(Aero);<br />
if Aero then<br />
begin<br />
Area:=Rect(-1,-1,-1,-1);<br />
Color:=clBlack;<br />
@DwmExtendFrameIntoClientArea:=GetProcAddress(hDWM,'DwmExtendFrameIntoClientArea');<br />
if @DwmExtendFrameIntoClientArea<>nil then<br />
DwmExtendFrameIntoClientArea(Handle,@Area);<br />
<br />
end<br />
else ShowMessage('Aero is Disabled');<br />
finally<br />
FreeLibrary(hDWM);<br />
end;<br />
end;<br />
<br />
procedure TForm1.EnableBlur;<br />
const<br />
WCA_ACCENT_POLICY = 19;<br />
ACCENT_ENABLE_BLURBEHIND = 3;<br />
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4;<br />
DrawLeftBorder = $20;<br />
DrawTopBorder = $40;<br />
DrawRightBorder = $80;<br />
DrawBottomBorder = $100;<br />
var<br />
dwm10: THandle;<br />
data : TWinCompAttrData;<br />
accent: AccentPolicy;<br />
begin<br />
<br />
dwm10 := LoadLibrary('user32.dll');<br />
try<br />
@SetWindowCompositionAttribute := GetProcAddress(dwm10, 'SetWindowCompositionAttribute');<br />
if @SetWindowCompositionAttribute <> nil then<br />
begin<br />
accent.AccentState := ACCENT_ENABLE_BLURBEHIND ;<br />
//accent.AccentState := ACCENT_ENABLE_ACRYLICBLURBEHIND;<br />
accent.GradientColor := (100 SHL 24) or ($00E3E0DE);<br />
accent.AccentFlags := DrawLeftBorder or DrawTopBorder or DrawRightBorder or DrawBottomBorder;<br />
<br />
data.Attribute := WCA_ACCENT_POLICY;<br />
data.dataSize := SizeOf(accent);<br />
data.pData := @accent;<br />
SetWindowCompositionAttribute(self.Handle, data);<br />
end<br />
else<br />
begin<br />
ShowMessage('Not found Windows 10 blur API');<br />
end;<br />
finally<br />
FreeLibrary(dwm10);<br />
end;<br />
<br />
end;<br />
<br />
procedure TForm1.FormCreate(Sender: TObject);<br />
begin<br />
DoubleBuffered := True;<br />
Color := clBlack;<br />
BorderStyle := bsnoNe;<br />
BorderIcons := [biSystemMenu, biMinimize, biMaximize];<br />
//AeroGlass;<br />
if TaskbarTranslucent then<br />
EnableBlur;<br />
<br />
UpdateColorization;<br />
end;<br />
<br />
procedure TForm1.BCButtonFocus1Click(Sender: TObject);<br />
begin<br />
close;<br />
end;<br />
<br />
function TForm1.TaskbarAccented: boolean;<br />
var<br />
reg: TRegistry;<br />
begin<br />
Result := False;<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CURRENT_USER;<br />
reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize');<br />
try<br />
if reg.ReadInteger('ColorPrevalence') = 1 then<br />
Result := True;<br />
except<br />
Result := False;<br />
end;<br />
reg.CloseKey;<br />
<br />
finally<br />
reg.Free;<br />
end;<br />
end;<br />
<br />
function TForm1.TaskbarTranslucent: boolean;<br />
var<br />
reg: TRegistry;<br />
begin<br />
Result := False;<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CURRENT_USER;<br />
reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize');<br />
try<br />
if reg.ReadInteger('EnableTransparency') = 1 then<br />
Result := True;<br />
except<br />
Result := False;<br />
end;<br />
reg.CloseKey;<br />
<br />
finally<br />
reg.Free;<br />
end;<br />
end;<br />
<br />
<br />
<br />
procedure TForm1.UpdateColorization;<br />
begin<br />
if TaskbarTranslucent then<br />
begin<br />
SetAlphaColorPicture(clblack, 200, Image1.Picture, 10,10 );<br />
Image1.Align := alClient;<br />
Image1.Stretch := True;<br />
Image1.Visible := True;<br />
end<br />
else<br />
Image1.Visible := False;<br />
<br />
if TaskbarAccented then<br />
begin<br />
SetAlphaColorPicture(9338482, 110, Image2.Picture, 10, 10);<br />
Image2.Visible := True;<br />
Image2.Align := alClient;<br />
Image2.Stretch := True;<br />
end<br />
else<br />
Image2.Visible := False;<br />
end;<br />
<br />
function TForm1.GetAccentColor:TColor;<br />
var<br />
col: cardinal;<br />
opaque: longbool;<br />
newcolor: TColor;<br />
a,r,g,b: byte;<br />
begin<br />
DwmGetColorizationColor(col, opaque);<br />
a := Byte(col shr 24);<br />
r := Byte(col shr 16);<br />
g := Byte(col shr 8);<br />
b := Byte(col);<br />
<br />
<br />
newcolor := RGB(<br />
round(r*(a/255)+255-a),<br />
round(g*(a/255)+255-a),<br />
round(b*(a/255)+255-a)<br />
);<br />
<br />
Result := newcolor;<br />
<br />
<br />
end;<br />
<br />
<br />
initialization<br />
SetWindowCompositionAttribute := GetProcAddress(GetModuleHandle(user32), 'SetWindowCompositionAttribute');<br />
end.<br />
</syntaxhighlight><br />
<br />
== Bugs ==<br />
<br />
As you can see in the first image Labels aren't displayed fine in Aero Glass, there are links with components and code that show how to make "Glow Labels":<br />
<br />
*[http://development.mwcs.de/glowlabel.html GlowLabel for Delphi]<br />
*[http://www.delphipraxis.net/953968-post4.html Aero Glass - ein Text (Label) hintergrund "machen"]<br />
<br />
Also if you clic the transparent part of the window the back window / desktop is selected (focus is lost in the form with aero glass).<br />
<br />
== About ==<br />
<br />
This was converted to Lazarus using "{$mode delphi}" from "Aero Glass Effekt für Delphi-Forms, Delphi-Unit von Daniel Mitte (2006)":<br />
<br />
*[http://www.delphipraxis.net/74538-aero-glass-effekt-fuer-delphi-forms.html Aero Glass Effekt für Delphi-Forms]<br />
<br />
There is a Delphi component here (to be ported in Lazarus):<br />
<br />
*[http://www.torry.net/authorsmore.php?id=6179 D. Mitte in Torry's Delphi Page]<br />
<br />
[[Category:Tutorials]]<br />
[[Category:Windows]]</div>007https://wiki.freepascal.org/index.php?title=File:aeroglasswin10.png&diff=137395File:aeroglasswin10.png2020-06-24T23:51:47Z<p>007: </p>
<hr />
<div></div>007https://wiki.freepascal.org/index.php?title=Aero_Glass&diff=137394Aero Glass2020-06-24T23:51:32Z<p>007: /* Windows 10 */</p>
<hr />
<div>{{Platform only|Windows|Windows|Windows}}<br />
{{Aero Glass}}<br />
<br />
== Aero Glass effect on Lazarus Form ==<br />
<br />
[[Image:aero_glass_lazarus.png]]<br />
<br />
First save the above code to a text file "glass.pas":<br />
<br />
<syntaxhighlight lang=pascal>unit glass;<br />
<br />
{$mode delphi}<br />
//{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Windows, Forms, Graphics;<br />
<br />
type<br />
_MARGINS = packed record<br />
cxLeftWidth : Integer;<br />
cxRightWidth : Integer;<br />
cyTopHeight : Integer;<br />
cyBottomHeight : Integer;<br />
end;<br />
<br />
PMargins = ^_MARGINS;<br />
TMargins = _MARGINS;<br />
<br />
DwmIsCompositionEnabledFunc = function(pfEnabled: PBoolean): HRESULT; stdcall;<br />
DwmExtendFrameIntoClientAreaFunc = function(destWnd: HWND; const pMarInset: PMargins): HRESULT; stdcall;<br />
SetLayeredWindowAttributesFunc = function(destWnd: HWND; cKey: TColor; bAlpha: Byte; dwFlags: DWord): BOOL; stdcall;<br />
<br />
const<br />
WS_EX_LAYERED = $80000;<br />
LWA_COLORKEY = 1;<br />
<br />
procedure GlassForm(frm: TForm; tmpMargins: TMargins; cBlurColorKey: TColor = clFuchsia);<br />
function WindowsAeroGlassCompatible: Boolean;<br />
<br />
implementation<br />
<br />
function WindowsAeroGlassCompatible: Boolean;<br />
var<br />
osVinfo: TOSVERSIONINFO;<br />
begin<br />
ZeroMemory(@osVinfo, SizeOf(osVinfo));<br />
OsVinfo.dwOSVersionInfoSize := SizeOf(TOSVERSIONINFO);<br />
if (<br />
(GetVersionEx(osVInfo) = True) and<br />
(osVinfo.dwPlatformId = VER_PLATFORM_WIN32_NT) and<br />
(osVinfo.dwMajorVersion >= 6)<br />
)<br />
then Result:=True<br />
else Result:=False;<br />
end;<br />
<br />
procedure GlassForm(frm: TForm; tmpMargins: TMargins; cBlurColorKey: TColor = clFuchsia);<br />
var<br />
hDwmDLL: Cardinal;<br />
fDwmIsCompositionEnabled: DwmIsCompositionEnabledFunc;<br />
fDwmExtendFrameIntoClientArea: DwmExtendFrameIntoClientAreaFunc;<br />
fSetLayeredWindowAttributesFunc: SetLayeredWindowAttributesFunc;<br />
bCmpEnable: Boolean;<br />
mgn: TMargins;<br />
begin<br />
{ Continue if Windows version is compatible }<br />
if WindowsAeroGlassCompatible then begin<br />
{ Continue if 'dwmapi' library is loaded }<br />
hDwmDLL := LoadLibrary('dwmapi.dll');<br />
if hDwmDLL <> 0 then begin<br />
{ Get values }<br />
@fDwmIsCompositionEnabled := GetProcAddress(hDwmDLL, 'DwmIsCompositionEnabled');<br />
@fDwmExtendFrameIntoClientArea := GetProcAddress(hDwmDLL, 'DwmExtendFrameIntoClientArea');<br />
@fSetLayeredWindowAttributesFunc := GetProcAddress(GetModulehandle(user32), 'SetLayeredWindowAttributes');<br />
{ Continue if values are <> nil }<br />
if (<br />
(@fDwmIsCompositionEnabled <> nil) and<br />
(@fDwmExtendFrameIntoClientArea <> nil) and<br />
(@fSetLayeredWindowAttributesFunc <> nil)<br />
)<br />
then begin<br />
{ Continue if composition is enabled }<br />
fDwmIsCompositionEnabled(@bCmpEnable);<br />
if bCmpEnable = True then begin<br />
{ Set Form Color same as cBlurColorKey }<br />
frm.Color := cBlurColorKey;<br />
{ ... }<br />
SetWindowLong(frm.Handle, GWL_EXSTYLE, GetWindowLong(frm.Handle, GWL_EXSTYLE) or WS_EX_LAYERED);<br />
{ ... }<br />
fSetLayeredWindowAttributesFunc(frm.Handle, cBlurColorKey, 0, LWA_COLORKEY);<br />
{ Set margins }<br />
ZeroMemory(@mgn, SizeOf(mgn));<br />
mgn.cxLeftWidth := tmpMargins.cxLeftWidth;<br />
mgn.cxRightWidth := tmpMargins.cxRightWidth;<br />
mgn.cyTopHeight := tmpMargins.cyTopHeight;<br />
mgn.cyBottomHeight := tmpMargins.cyBottomHeight;<br />
{ Extend Form }<br />
fDwmExtendFrameIntoClientArea(frm.Handle,@mgn);<br />
end;<br />
end;<br />
{ Free loaded 'dwmapi' library }<br />
FreeLibrary(hDWMDLL);<br />
end;<br />
end;<br />
end;<br />
<br />
end.</syntaxhighlight><br />
<br />
Copy the "glass.pas" file to the main folder of your project:<br />
<br />
MyProject\glass.pas<br />
<br />
In the "uses" section of your project you need to add "glass":<br />
<br />
<syntaxhighlight lang=pascal>unit form1;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs<br />
glass; // This includes GlassForm procedure </syntaxhighlight><br />
<br />
OnActivate event of each form call the procedure in this way:<br />
<br />
<syntaxhighlight lang=pascal>procedure TForm1.FormActivate(Sender: TObject);<br />
var<br />
tmpMargins: TMargins;<br />
begin<br />
{ If all margins are -1 the whole form will be aero glass}<br />
tmpMargins.cxLeftWidth := -1;<br />
tmpMargins.cxRightWidth := -1;<br />
tmpMargins.cyBottomHeight := -1;<br />
tmpMargins.cyTopHeight := -1;<br />
{ FormName ; Margins ; TransparentColor }<br />
GlassForm(Self, tmpMargins, clFuchsia); <br />
end;</syntaxhighlight><br />
<br />
Also you need to enable Themes to use this procedure, go to Options > Project Options > then select "Use Manifest to Enable Themes (Windows)".<br />
<br />
== Windows 10 ==<br />
<br />
[[File:aeroglasswin10.png]]<br />
<br />
<syntaxhighlight lang=pascal><br />
{<br />
author: vhanla<br />
http://vhanla.codigobit.info<br />
}<br />
unit Unit1;<br />
<br />
interface<br />
<br />
uses<br />
Windows, Messages, SysUtils, Variants, Classes, Graphics,<br />
Controls, Forms, Dialogs, DWMApi, png, IntfGraphics, FPImage, GraphType,<br />
StdCtrls, ExtCtrls, BCButtonFocus, BCLabel, Registry, LMessages, LCLType, LCLIntf;<br />
<br />
type<br />
<br />
{ TForm1 }<br />
<br />
TForm1 = class(TForm)<br />
BCButtonFocus1: TBCButtonFocus;<br />
BCLabel1: TBCLabel;<br />
Image1: TImage;<br />
Image2: TImage;<br />
Panel1: TPanel;<br />
<br />
procedure BCButtonFocus1Click(Sender: TObject);<br />
procedure FormCreate(Sender: TObject);<br />
procedure Button1Click(Sender: TObject);<br />
procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton;<br />
Shift: TShiftState; X, Y: Integer);<br />
private<br />
{ Private declarations }<br />
function TaskbarAccented:boolean;<br />
function TaskbarTranslucent:boolean;<br />
procedure EnableBlur;<br />
procedure AeroGlass;<br />
procedure UpdateColorization;<br />
function GetAccentColor:TColor;<br />
public<br />
{ Public declarations }<br />
end;<br />
<br />
AccentPolicy = packed record<br />
AccentState: Integer;<br />
AccentFlags: Integer;<br />
GradientColor: Integer;<br />
AnimationId: Integer;<br />
end;<br />
<br />
TWinCompAttrData = packed record<br />
attribute: THandle;<br />
pData: Pointer;<br />
dataSize: ULONG;<br />
end;<br />
<br />
<br />
var<br />
Form1: TForm1;<br />
<br />
var<br />
SetWindowCompositionAttribute: function (Wnd: HWND; const AttrData: TWinCompAttrData): BOOL; stdcall = Nil;<br />
implementation<br />
<br />
{$R *.lfm}<br />
<br />
procedure SetAlphaColorPicture(<br />
const Col: TColor;<br />
const Alpha: Integer;<br />
Picture: TPicture;<br />
const _width: Integer;<br />
const _height: Integer<br />
);<br />
var<br />
IM: TLazIntfImage;<br />
x,y: integer;<br />
sl: pByteArray;<br />
I, J, W, H: Integer;<br />
FC: TFPColor;<br />
begin<br />
IM := TLazIntfImage.Create(0, 0, [riqfRGB, riqfAlpha]);<br />
try<br />
IM.SetSize(_width, _height);<br />
for I := 0 to _width - 1 do<br />
begin<br />
for J := 0 to _height - 1 do<br />
begin<br />
FC.red := (128 + I) shl 8;<br />
FC.green := (128 + J) shl 8;<br />
FC.blue := 128 shl 8;<br />
FC.alpha := 128 shl 8; // now works fine<br />
IM.Colors[I, J] := FC;<br />
end;<br />
end;<br />
Picture.Assign(IM);<br />
<br />
<br />
finally<br />
IM.Free;<br />
<br />
end;<br />
end;<br />
<br />
procedure TForm1.Button1Click(Sender: TObject);<br />
begin<br />
Close;<br />
end;<br />
<br />
procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;<br />
Shift: TShiftState; X, Y: Integer);<br />
begin<br />
ReleaseCapture;<br />
SendMessage(Form1.Handle, LM_SYSCOMMAND, 61458, 0) ;<br />
end;<br />
<br />
procedure TForm1.AeroGlass;<br />
var<br />
Aero: BOOL;<br />
Area: TRect;<br />
hDWM: THandle;<br />
begin<br />
hDWM:=LoadLibrary('dwmapi.dll');<br />
try<br />
@DwmIsCompositionEnabled:=GetProcAddress(hDWM,'DwmIsCompositionEnabled');<br />
if @DwmIsCompositionEnabled<>nil then<br />
DwmIsCompositionEnabled(Aero);<br />
if Aero then<br />
begin<br />
Area:=Rect(-1,-1,-1,-1);<br />
Color:=clBlack;<br />
@DwmExtendFrameIntoClientArea:=GetProcAddress(hDWM,'DwmExtendFrameIntoClientArea');<br />
if @DwmExtendFrameIntoClientArea<>nil then<br />
DwmExtendFrameIntoClientArea(Handle,@Area);<br />
<br />
end<br />
else ShowMessage('Aero is Disabled');<br />
finally<br />
FreeLibrary(hDWM);<br />
end;<br />
end;<br />
<br />
procedure TForm1.EnableBlur;<br />
const<br />
WCA_ACCENT_POLICY = 19;<br />
ACCENT_ENABLE_BLURBEHIND = 3;<br />
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4;<br />
DrawLeftBorder = $20;<br />
DrawTopBorder = $40;<br />
DrawRightBorder = $80;<br />
DrawBottomBorder = $100;<br />
var<br />
dwm10: THandle;<br />
data : TWinCompAttrData;<br />
accent: AccentPolicy;<br />
begin<br />
<br />
dwm10 := LoadLibrary('user32.dll');<br />
try<br />
@SetWindowCompositionAttribute := GetProcAddress(dwm10, 'SetWindowCompositionAttribute');<br />
if @SetWindowCompositionAttribute <> nil then<br />
begin<br />
accent.AccentState := ACCENT_ENABLE_BLURBEHIND ;<br />
//accent.AccentState := ACCENT_ENABLE_ACRYLICBLURBEHIND;<br />
accent.GradientColor := (100 SHL 24) or ($00E3E0DE);<br />
accent.AccentFlags := DrawLeftBorder or DrawTopBorder or DrawRightBorder or DrawBottomBorder;<br />
<br />
data.Attribute := WCA_ACCENT_POLICY;<br />
data.dataSize := SizeOf(accent);<br />
data.pData := @accent;<br />
SetWindowCompositionAttribute(self.Handle, data);<br />
end<br />
else<br />
begin<br />
ShowMessage('Not found Windows 10 blur API');<br />
end;<br />
finally<br />
FreeLibrary(dwm10);<br />
end;<br />
<br />
end;<br />
<br />
procedure TForm1.FormCreate(Sender: TObject);<br />
begin<br />
DoubleBuffered := True;<br />
Color := clBlack;<br />
BorderStyle := bsnoNe;<br />
BorderIcons := [biSystemMenu, biMinimize, biMaximize];<br />
//AeroGlass;<br />
if TaskbarTranslucent then<br />
EnableBlur;<br />
<br />
UpdateColorization;<br />
end;<br />
<br />
procedure TForm1.BCButtonFocus1Click(Sender: TObject);<br />
begin<br />
close;<br />
end;<br />
<br />
function TForm1.TaskbarAccented: boolean;<br />
var<br />
reg: TRegistry;<br />
begin<br />
Result := False;<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CURRENT_USER;<br />
reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize');<br />
try<br />
if reg.ReadInteger('ColorPrevalence') = 1 then<br />
Result := True;<br />
except<br />
Result := False;<br />
end;<br />
reg.CloseKey;<br />
<br />
finally<br />
reg.Free;<br />
end;<br />
end;<br />
<br />
function TForm1.TaskbarTranslucent: boolean;<br />
var<br />
reg: TRegistry;<br />
begin<br />
Result := False;<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CURRENT_USER;<br />
reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize');<br />
try<br />
if reg.ReadInteger('EnableTransparency') = 1 then<br />
Result := True;<br />
except<br />
Result := False;<br />
end;<br />
reg.CloseKey;<br />
<br />
finally<br />
reg.Free;<br />
end;<br />
end;<br />
<br />
<br />
<br />
procedure TForm1.UpdateColorization;<br />
begin<br />
if TaskbarTranslucent then<br />
begin<br />
SetAlphaColorPicture(clblack, 200, Image1.Picture, 10,10 );<br />
Image1.Align := alClient;<br />
Image1.Stretch := True;<br />
Image1.Visible := True;<br />
end<br />
else<br />
Image1.Visible := False;<br />
<br />
if TaskbarAccented then<br />
begin<br />
SetAlphaColorPicture(9338482, 110, Image2.Picture, 10, 10);<br />
Image2.Visible := True;<br />
Image2.Align := alClient;<br />
Image2.Stretch := True;<br />
end<br />
else<br />
Image2.Visible := False;<br />
end;<br />
<br />
function TForm1.GetAccentColor:TColor;<br />
var<br />
col: cardinal;<br />
opaque: longbool;<br />
newcolor: TColor;<br />
a,r,g,b: byte;<br />
begin<br />
DwmGetColorizationColor(col, opaque);<br />
a := Byte(col shr 24);<br />
r := Byte(col shr 16);<br />
g := Byte(col shr 8);<br />
b := Byte(col);<br />
<br />
<br />
newcolor := RGB(<br />
round(r*(a/255)+255-a),<br />
round(g*(a/255)+255-a),<br />
round(b*(a/255)+255-a)<br />
);<br />
<br />
Result := newcolor;<br />
<br />
<br />
end;<br />
<br />
<br />
initialization<br />
SetWindowCompositionAttribute := GetProcAddress(GetModuleHandle(user32), 'SetWindowCompositionAttribute');<br />
end.<br />
</syntaxhighlight><br />
<br />
== Bugs ==<br />
<br />
As you can see in the first image Labels aren't displayed fine in Aero Glass, there are links with components and code that show how to make "Glow Labels":<br />
<br />
*[http://development.mwcs.de/glowlabel.html GlowLabel for Delphi]<br />
*[http://www.delphipraxis.net/953968-post4.html Aero Glass - ein Text (Label) hintergrund "machen"]<br />
<br />
Also if you clic the transparent part of the window the back window / desktop is selected (focus is lost in the form with aero glass).<br />
<br />
== About ==<br />
<br />
This was converted to Lazarus using "{$mode delphi}" from "Aero Glass Effekt für Delphi-Forms, Delphi-Unit von Daniel Mitte (2006)":<br />
<br />
*[http://www.delphipraxis.net/74538-aero-glass-effekt-fuer-delphi-forms.html Aero Glass Effekt für Delphi-Forms]<br />
<br />
There is a Delphi component here (to be ported in Lazarus):<br />
<br />
*[http://www.torry.net/authorsmore.php?id=6179 D. Mitte in Torry's Delphi Page]<br />
<br />
[[Category:Tutorials]]<br />
[[Category:Windows]]</div>007https://wiki.freepascal.org/index.php?title=Aero_Glass&diff=137393Aero Glass2020-06-24T23:50:54Z<p>007: /* Windows 10 */</p>
<hr />
<div>{{Platform only|Windows|Windows|Windows}}<br />
{{Aero Glass}}<br />
<br />
== Aero Glass effect on Lazarus Form ==<br />
<br />
[[Image:aero_glass_lazarus.png]]<br />
<br />
First save the above code to a text file "glass.pas":<br />
<br />
<syntaxhighlight lang=pascal>unit glass;<br />
<br />
{$mode delphi}<br />
//{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Windows, Forms, Graphics;<br />
<br />
type<br />
_MARGINS = packed record<br />
cxLeftWidth : Integer;<br />
cxRightWidth : Integer;<br />
cyTopHeight : Integer;<br />
cyBottomHeight : Integer;<br />
end;<br />
<br />
PMargins = ^_MARGINS;<br />
TMargins = _MARGINS;<br />
<br />
DwmIsCompositionEnabledFunc = function(pfEnabled: PBoolean): HRESULT; stdcall;<br />
DwmExtendFrameIntoClientAreaFunc = function(destWnd: HWND; const pMarInset: PMargins): HRESULT; stdcall;<br />
SetLayeredWindowAttributesFunc = function(destWnd: HWND; cKey: TColor; bAlpha: Byte; dwFlags: DWord): BOOL; stdcall;<br />
<br />
const<br />
WS_EX_LAYERED = $80000;<br />
LWA_COLORKEY = 1;<br />
<br />
procedure GlassForm(frm: TForm; tmpMargins: TMargins; cBlurColorKey: TColor = clFuchsia);<br />
function WindowsAeroGlassCompatible: Boolean;<br />
<br />
implementation<br />
<br />
function WindowsAeroGlassCompatible: Boolean;<br />
var<br />
osVinfo: TOSVERSIONINFO;<br />
begin<br />
ZeroMemory(@osVinfo, SizeOf(osVinfo));<br />
OsVinfo.dwOSVersionInfoSize := SizeOf(TOSVERSIONINFO);<br />
if (<br />
(GetVersionEx(osVInfo) = True) and<br />
(osVinfo.dwPlatformId = VER_PLATFORM_WIN32_NT) and<br />
(osVinfo.dwMajorVersion >= 6)<br />
)<br />
then Result:=True<br />
else Result:=False;<br />
end;<br />
<br />
procedure GlassForm(frm: TForm; tmpMargins: TMargins; cBlurColorKey: TColor = clFuchsia);<br />
var<br />
hDwmDLL: Cardinal;<br />
fDwmIsCompositionEnabled: DwmIsCompositionEnabledFunc;<br />
fDwmExtendFrameIntoClientArea: DwmExtendFrameIntoClientAreaFunc;<br />
fSetLayeredWindowAttributesFunc: SetLayeredWindowAttributesFunc;<br />
bCmpEnable: Boolean;<br />
mgn: TMargins;<br />
begin<br />
{ Continue if Windows version is compatible }<br />
if WindowsAeroGlassCompatible then begin<br />
{ Continue if 'dwmapi' library is loaded }<br />
hDwmDLL := LoadLibrary('dwmapi.dll');<br />
if hDwmDLL <> 0 then begin<br />
{ Get values }<br />
@fDwmIsCompositionEnabled := GetProcAddress(hDwmDLL, 'DwmIsCompositionEnabled');<br />
@fDwmExtendFrameIntoClientArea := GetProcAddress(hDwmDLL, 'DwmExtendFrameIntoClientArea');<br />
@fSetLayeredWindowAttributesFunc := GetProcAddress(GetModulehandle(user32), 'SetLayeredWindowAttributes');<br />
{ Continue if values are <> nil }<br />
if (<br />
(@fDwmIsCompositionEnabled <> nil) and<br />
(@fDwmExtendFrameIntoClientArea <> nil) and<br />
(@fSetLayeredWindowAttributesFunc <> nil)<br />
)<br />
then begin<br />
{ Continue if composition is enabled }<br />
fDwmIsCompositionEnabled(@bCmpEnable);<br />
if bCmpEnable = True then begin<br />
{ Set Form Color same as cBlurColorKey }<br />
frm.Color := cBlurColorKey;<br />
{ ... }<br />
SetWindowLong(frm.Handle, GWL_EXSTYLE, GetWindowLong(frm.Handle, GWL_EXSTYLE) or WS_EX_LAYERED);<br />
{ ... }<br />
fSetLayeredWindowAttributesFunc(frm.Handle, cBlurColorKey, 0, LWA_COLORKEY);<br />
{ Set margins }<br />
ZeroMemory(@mgn, SizeOf(mgn));<br />
mgn.cxLeftWidth := tmpMargins.cxLeftWidth;<br />
mgn.cxRightWidth := tmpMargins.cxRightWidth;<br />
mgn.cyTopHeight := tmpMargins.cyTopHeight;<br />
mgn.cyBottomHeight := tmpMargins.cyBottomHeight;<br />
{ Extend Form }<br />
fDwmExtendFrameIntoClientArea(frm.Handle,@mgn);<br />
end;<br />
end;<br />
{ Free loaded 'dwmapi' library }<br />
FreeLibrary(hDWMDLL);<br />
end;<br />
end;<br />
end;<br />
<br />
end.</syntaxhighlight><br />
<br />
Copy the "glass.pas" file to the main folder of your project:<br />
<br />
MyProject\glass.pas<br />
<br />
In the "uses" section of your project you need to add "glass":<br />
<br />
<syntaxhighlight lang=pascal>unit form1;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs<br />
glass; // This includes GlassForm procedure </syntaxhighlight><br />
<br />
OnActivate event of each form call the procedure in this way:<br />
<br />
<syntaxhighlight lang=pascal>procedure TForm1.FormActivate(Sender: TObject);<br />
var<br />
tmpMargins: TMargins;<br />
begin<br />
{ If all margins are -1 the whole form will be aero glass}<br />
tmpMargins.cxLeftWidth := -1;<br />
tmpMargins.cxRightWidth := -1;<br />
tmpMargins.cyBottomHeight := -1;<br />
tmpMargins.cyTopHeight := -1;<br />
{ FormName ; Margins ; TransparentColor }<br />
GlassForm(Self, tmpMargins, clFuchsia); <br />
end;</syntaxhighlight><br />
<br />
Also you need to enable Themes to use this procedure, go to Options > Project Options > then select "Use Manifest to Enable Themes (Windows)".<br />
<br />
== Windows 10 ==<br />
<br />
[[File:aeroglasswin10.jpg]]<br />
<br />
<syntaxhighlight lang=pascal><br />
{<br />
author: vhanla<br />
http://vhanla.codigobit.info<br />
}<br />
unit Unit1;<br />
<br />
interface<br />
<br />
uses<br />
Windows, Messages, SysUtils, Variants, Classes, Graphics,<br />
Controls, Forms, Dialogs, DWMApi, png, IntfGraphics, FPImage, GraphType,<br />
StdCtrls, ExtCtrls, BCButtonFocus, BCLabel, Registry, LMessages, LCLType, LCLIntf;<br />
<br />
type<br />
<br />
{ TForm1 }<br />
<br />
TForm1 = class(TForm)<br />
BCButtonFocus1: TBCButtonFocus;<br />
BCLabel1: TBCLabel;<br />
Image1: TImage;<br />
Image2: TImage;<br />
Panel1: TPanel;<br />
<br />
procedure BCButtonFocus1Click(Sender: TObject);<br />
procedure FormCreate(Sender: TObject);<br />
procedure Button1Click(Sender: TObject);<br />
procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton;<br />
Shift: TShiftState; X, Y: Integer);<br />
private<br />
{ Private declarations }<br />
function TaskbarAccented:boolean;<br />
function TaskbarTranslucent:boolean;<br />
procedure EnableBlur;<br />
procedure AeroGlass;<br />
procedure UpdateColorization;<br />
function GetAccentColor:TColor;<br />
public<br />
{ Public declarations }<br />
end;<br />
<br />
AccentPolicy = packed record<br />
AccentState: Integer;<br />
AccentFlags: Integer;<br />
GradientColor: Integer;<br />
AnimationId: Integer;<br />
end;<br />
<br />
TWinCompAttrData = packed record<br />
attribute: THandle;<br />
pData: Pointer;<br />
dataSize: ULONG;<br />
end;<br />
<br />
<br />
var<br />
Form1: TForm1;<br />
<br />
var<br />
SetWindowCompositionAttribute: function (Wnd: HWND; const AttrData: TWinCompAttrData): BOOL; stdcall = Nil;<br />
implementation<br />
<br />
{$R *.lfm}<br />
<br />
procedure SetAlphaColorPicture(<br />
const Col: TColor;<br />
const Alpha: Integer;<br />
Picture: TPicture;<br />
const _width: Integer;<br />
const _height: Integer<br />
);<br />
var<br />
IM: TLazIntfImage;<br />
x,y: integer;<br />
sl: pByteArray;<br />
I, J, W, H: Integer;<br />
FC: TFPColor;<br />
begin<br />
IM := TLazIntfImage.Create(0, 0, [riqfRGB, riqfAlpha]);<br />
try<br />
IM.SetSize(_width, _height);<br />
for I := 0 to _width - 1 do<br />
begin<br />
for J := 0 to _height - 1 do<br />
begin<br />
FC.red := (128 + I) shl 8;<br />
FC.green := (128 + J) shl 8;<br />
FC.blue := 128 shl 8;<br />
FC.alpha := 128 shl 8; // now works fine<br />
IM.Colors[I, J] := FC;<br />
end;<br />
end;<br />
Picture.Assign(IM);<br />
<br />
<br />
finally<br />
IM.Free;<br />
<br />
end;<br />
end;<br />
<br />
procedure TForm1.Button1Click(Sender: TObject);<br />
begin<br />
Close;<br />
end;<br />
<br />
procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;<br />
Shift: TShiftState; X, Y: Integer);<br />
begin<br />
ReleaseCapture;<br />
SendMessage(Form1.Handle, LM_SYSCOMMAND, 61458, 0) ;<br />
end;<br />
<br />
procedure TForm1.AeroGlass;<br />
var<br />
Aero: BOOL;<br />
Area: TRect;<br />
hDWM: THandle;<br />
begin<br />
hDWM:=LoadLibrary('dwmapi.dll');<br />
try<br />
@DwmIsCompositionEnabled:=GetProcAddress(hDWM,'DwmIsCompositionEnabled');<br />
if @DwmIsCompositionEnabled<>nil then<br />
DwmIsCompositionEnabled(Aero);<br />
if Aero then<br />
begin<br />
Area:=Rect(-1,-1,-1,-1);<br />
Color:=clBlack;<br />
@DwmExtendFrameIntoClientArea:=GetProcAddress(hDWM,'DwmExtendFrameIntoClientArea');<br />
if @DwmExtendFrameIntoClientArea<>nil then<br />
DwmExtendFrameIntoClientArea(Handle,@Area);<br />
<br />
end<br />
else ShowMessage('Aero is Disabled');<br />
finally<br />
FreeLibrary(hDWM);<br />
end;<br />
end;<br />
<br />
procedure TForm1.EnableBlur;<br />
const<br />
WCA_ACCENT_POLICY = 19;<br />
ACCENT_ENABLE_BLURBEHIND = 3;<br />
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4;<br />
DrawLeftBorder = $20;<br />
DrawTopBorder = $40;<br />
DrawRightBorder = $80;<br />
DrawBottomBorder = $100;<br />
var<br />
dwm10: THandle;<br />
data : TWinCompAttrData;<br />
accent: AccentPolicy;<br />
begin<br />
<br />
dwm10 := LoadLibrary('user32.dll');<br />
try<br />
@SetWindowCompositionAttribute := GetProcAddress(dwm10, 'SetWindowCompositionAttribute');<br />
if @SetWindowCompositionAttribute <> nil then<br />
begin<br />
accent.AccentState := ACCENT_ENABLE_BLURBEHIND ;<br />
//accent.AccentState := ACCENT_ENABLE_ACRYLICBLURBEHIND;<br />
accent.GradientColor := (100 SHL 24) or ($00E3E0DE);<br />
accent.AccentFlags := DrawLeftBorder or DrawTopBorder or DrawRightBorder or DrawBottomBorder;<br />
<br />
data.Attribute := WCA_ACCENT_POLICY;<br />
data.dataSize := SizeOf(accent);<br />
data.pData := @accent;<br />
SetWindowCompositionAttribute(self.Handle, data);<br />
end<br />
else<br />
begin<br />
ShowMessage('Not found Windows 10 blur API');<br />
end;<br />
finally<br />
FreeLibrary(dwm10);<br />
end;<br />
<br />
end;<br />
<br />
procedure TForm1.FormCreate(Sender: TObject);<br />
begin<br />
DoubleBuffered := True;<br />
Color := clBlack;<br />
BorderStyle := bsnoNe;<br />
BorderIcons := [biSystemMenu, biMinimize, biMaximize];<br />
//AeroGlass;<br />
if TaskbarTranslucent then<br />
EnableBlur;<br />
<br />
UpdateColorization;<br />
end;<br />
<br />
procedure TForm1.BCButtonFocus1Click(Sender: TObject);<br />
begin<br />
close;<br />
end;<br />
<br />
function TForm1.TaskbarAccented: boolean;<br />
var<br />
reg: TRegistry;<br />
begin<br />
Result := False;<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CURRENT_USER;<br />
reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize');<br />
try<br />
if reg.ReadInteger('ColorPrevalence') = 1 then<br />
Result := True;<br />
except<br />
Result := False;<br />
end;<br />
reg.CloseKey;<br />
<br />
finally<br />
reg.Free;<br />
end;<br />
end;<br />
<br />
function TForm1.TaskbarTranslucent: boolean;<br />
var<br />
reg: TRegistry;<br />
begin<br />
Result := False;<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CURRENT_USER;<br />
reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize');<br />
try<br />
if reg.ReadInteger('EnableTransparency') = 1 then<br />
Result := True;<br />
except<br />
Result := False;<br />
end;<br />
reg.CloseKey;<br />
<br />
finally<br />
reg.Free;<br />
end;<br />
end;<br />
<br />
<br />
<br />
procedure TForm1.UpdateColorization;<br />
begin<br />
if TaskbarTranslucent then<br />
begin<br />
SetAlphaColorPicture(clblack, 200, Image1.Picture, 10,10 );<br />
Image1.Align := alClient;<br />
Image1.Stretch := True;<br />
Image1.Visible := True;<br />
end<br />
else<br />
Image1.Visible := False;<br />
<br />
if TaskbarAccented then<br />
begin<br />
SetAlphaColorPicture(9338482, 110, Image2.Picture, 10, 10);<br />
Image2.Visible := True;<br />
Image2.Align := alClient;<br />
Image2.Stretch := True;<br />
end<br />
else<br />
Image2.Visible := False;<br />
end;<br />
<br />
function TForm1.GetAccentColor:TColor;<br />
var<br />
col: cardinal;<br />
opaque: longbool;<br />
newcolor: TColor;<br />
a,r,g,b: byte;<br />
begin<br />
DwmGetColorizationColor(col, opaque);<br />
a := Byte(col shr 24);<br />
r := Byte(col shr 16);<br />
g := Byte(col shr 8);<br />
b := Byte(col);<br />
<br />
<br />
newcolor := RGB(<br />
round(r*(a/255)+255-a),<br />
round(g*(a/255)+255-a),<br />
round(b*(a/255)+255-a)<br />
);<br />
<br />
Result := newcolor;<br />
<br />
<br />
end;<br />
<br />
<br />
initialization<br />
SetWindowCompositionAttribute := GetProcAddress(GetModuleHandle(user32), 'SetWindowCompositionAttribute');<br />
end.<br />
</syntaxhighlight><br />
<br />
== Bugs ==<br />
<br />
As you can see in the first image Labels aren't displayed fine in Aero Glass, there are links with components and code that show how to make "Glow Labels":<br />
<br />
*[http://development.mwcs.de/glowlabel.html GlowLabel for Delphi]<br />
*[http://www.delphipraxis.net/953968-post4.html Aero Glass - ein Text (Label) hintergrund "machen"]<br />
<br />
Also if you clic the transparent part of the window the back window / desktop is selected (focus is lost in the form with aero glass).<br />
<br />
== About ==<br />
<br />
This was converted to Lazarus using "{$mode delphi}" from "Aero Glass Effekt für Delphi-Forms, Delphi-Unit von Daniel Mitte (2006)":<br />
<br />
*[http://www.delphipraxis.net/74538-aero-glass-effekt-fuer-delphi-forms.html Aero Glass Effekt für Delphi-Forms]<br />
<br />
There is a Delphi component here (to be ported in Lazarus):<br />
<br />
*[http://www.torry.net/authorsmore.php?id=6179 D. Mitte in Torry's Delphi Page]<br />
<br />
[[Category:Tutorials]]<br />
[[Category:Windows]]</div>007https://wiki.freepascal.org/index.php?title=Aero_Glass&diff=137392Aero Glass2020-06-24T23:50:15Z<p>007: /* Aero Glass effect on Lazarus Form */</p>
<hr />
<div>{{Platform only|Windows|Windows|Windows}}<br />
{{Aero Glass}}<br />
<br />
== Aero Glass effect on Lazarus Form ==<br />
<br />
[[Image:aero_glass_lazarus.png]]<br />
<br />
First save the above code to a text file "glass.pas":<br />
<br />
<syntaxhighlight lang=pascal>unit glass;<br />
<br />
{$mode delphi}<br />
//{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Windows, Forms, Graphics;<br />
<br />
type<br />
_MARGINS = packed record<br />
cxLeftWidth : Integer;<br />
cxRightWidth : Integer;<br />
cyTopHeight : Integer;<br />
cyBottomHeight : Integer;<br />
end;<br />
<br />
PMargins = ^_MARGINS;<br />
TMargins = _MARGINS;<br />
<br />
DwmIsCompositionEnabledFunc = function(pfEnabled: PBoolean): HRESULT; stdcall;<br />
DwmExtendFrameIntoClientAreaFunc = function(destWnd: HWND; const pMarInset: PMargins): HRESULT; stdcall;<br />
SetLayeredWindowAttributesFunc = function(destWnd: HWND; cKey: TColor; bAlpha: Byte; dwFlags: DWord): BOOL; stdcall;<br />
<br />
const<br />
WS_EX_LAYERED = $80000;<br />
LWA_COLORKEY = 1;<br />
<br />
procedure GlassForm(frm: TForm; tmpMargins: TMargins; cBlurColorKey: TColor = clFuchsia);<br />
function WindowsAeroGlassCompatible: Boolean;<br />
<br />
implementation<br />
<br />
function WindowsAeroGlassCompatible: Boolean;<br />
var<br />
osVinfo: TOSVERSIONINFO;<br />
begin<br />
ZeroMemory(@osVinfo, SizeOf(osVinfo));<br />
OsVinfo.dwOSVersionInfoSize := SizeOf(TOSVERSIONINFO);<br />
if (<br />
(GetVersionEx(osVInfo) = True) and<br />
(osVinfo.dwPlatformId = VER_PLATFORM_WIN32_NT) and<br />
(osVinfo.dwMajorVersion >= 6)<br />
)<br />
then Result:=True<br />
else Result:=False;<br />
end;<br />
<br />
procedure GlassForm(frm: TForm; tmpMargins: TMargins; cBlurColorKey: TColor = clFuchsia);<br />
var<br />
hDwmDLL: Cardinal;<br />
fDwmIsCompositionEnabled: DwmIsCompositionEnabledFunc;<br />
fDwmExtendFrameIntoClientArea: DwmExtendFrameIntoClientAreaFunc;<br />
fSetLayeredWindowAttributesFunc: SetLayeredWindowAttributesFunc;<br />
bCmpEnable: Boolean;<br />
mgn: TMargins;<br />
begin<br />
{ Continue if Windows version is compatible }<br />
if WindowsAeroGlassCompatible then begin<br />
{ Continue if 'dwmapi' library is loaded }<br />
hDwmDLL := LoadLibrary('dwmapi.dll');<br />
if hDwmDLL <> 0 then begin<br />
{ Get values }<br />
@fDwmIsCompositionEnabled := GetProcAddress(hDwmDLL, 'DwmIsCompositionEnabled');<br />
@fDwmExtendFrameIntoClientArea := GetProcAddress(hDwmDLL, 'DwmExtendFrameIntoClientArea');<br />
@fSetLayeredWindowAttributesFunc := GetProcAddress(GetModulehandle(user32), 'SetLayeredWindowAttributes');<br />
{ Continue if values are <> nil }<br />
if (<br />
(@fDwmIsCompositionEnabled <> nil) and<br />
(@fDwmExtendFrameIntoClientArea <> nil) and<br />
(@fSetLayeredWindowAttributesFunc <> nil)<br />
)<br />
then begin<br />
{ Continue if composition is enabled }<br />
fDwmIsCompositionEnabled(@bCmpEnable);<br />
if bCmpEnable = True then begin<br />
{ Set Form Color same as cBlurColorKey }<br />
frm.Color := cBlurColorKey;<br />
{ ... }<br />
SetWindowLong(frm.Handle, GWL_EXSTYLE, GetWindowLong(frm.Handle, GWL_EXSTYLE) or WS_EX_LAYERED);<br />
{ ... }<br />
fSetLayeredWindowAttributesFunc(frm.Handle, cBlurColorKey, 0, LWA_COLORKEY);<br />
{ Set margins }<br />
ZeroMemory(@mgn, SizeOf(mgn));<br />
mgn.cxLeftWidth := tmpMargins.cxLeftWidth;<br />
mgn.cxRightWidth := tmpMargins.cxRightWidth;<br />
mgn.cyTopHeight := tmpMargins.cyTopHeight;<br />
mgn.cyBottomHeight := tmpMargins.cyBottomHeight;<br />
{ Extend Form }<br />
fDwmExtendFrameIntoClientArea(frm.Handle,@mgn);<br />
end;<br />
end;<br />
{ Free loaded 'dwmapi' library }<br />
FreeLibrary(hDWMDLL);<br />
end;<br />
end;<br />
end;<br />
<br />
end.</syntaxhighlight><br />
<br />
Copy the "glass.pas" file to the main folder of your project:<br />
<br />
MyProject\glass.pas<br />
<br />
In the "uses" section of your project you need to add "glass":<br />
<br />
<syntaxhighlight lang=pascal>unit form1;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs<br />
glass; // This includes GlassForm procedure </syntaxhighlight><br />
<br />
OnActivate event of each form call the procedure in this way:<br />
<br />
<syntaxhighlight lang=pascal>procedure TForm1.FormActivate(Sender: TObject);<br />
var<br />
tmpMargins: TMargins;<br />
begin<br />
{ If all margins are -1 the whole form will be aero glass}<br />
tmpMargins.cxLeftWidth := -1;<br />
tmpMargins.cxRightWidth := -1;<br />
tmpMargins.cyBottomHeight := -1;<br />
tmpMargins.cyTopHeight := -1;<br />
{ FormName ; Margins ; TransparentColor }<br />
GlassForm(Self, tmpMargins, clFuchsia); <br />
end;</syntaxhighlight><br />
<br />
Also you need to enable Themes to use this procedure, go to Options > Project Options > then select "Use Manifest to Enable Themes (Windows)".<br />
<br />
== Windows 10 ==<br />
<br />
<syntaxhighlight lang=pascal><br />
{<br />
author: vhanla<br />
http://vhanla.codigobit.info<br />
}<br />
unit Unit1;<br />
<br />
interface<br />
<br />
uses<br />
Windows, Messages, SysUtils, Variants, Classes, Graphics,<br />
Controls, Forms, Dialogs, DWMApi, png, IntfGraphics, FPImage, GraphType,<br />
StdCtrls, ExtCtrls, BCButtonFocus, BCLabel, Registry, LMessages, LCLType, LCLIntf;<br />
<br />
type<br />
<br />
{ TForm1 }<br />
<br />
TForm1 = class(TForm)<br />
BCButtonFocus1: TBCButtonFocus;<br />
BCLabel1: TBCLabel;<br />
Image1: TImage;<br />
Image2: TImage;<br />
Panel1: TPanel;<br />
<br />
procedure BCButtonFocus1Click(Sender: TObject);<br />
procedure FormCreate(Sender: TObject);<br />
procedure Button1Click(Sender: TObject);<br />
procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton;<br />
Shift: TShiftState; X, Y: Integer);<br />
private<br />
{ Private declarations }<br />
function TaskbarAccented:boolean;<br />
function TaskbarTranslucent:boolean;<br />
procedure EnableBlur;<br />
procedure AeroGlass;<br />
procedure UpdateColorization;<br />
function GetAccentColor:TColor;<br />
public<br />
{ Public declarations }<br />
end;<br />
<br />
AccentPolicy = packed record<br />
AccentState: Integer;<br />
AccentFlags: Integer;<br />
GradientColor: Integer;<br />
AnimationId: Integer;<br />
end;<br />
<br />
TWinCompAttrData = packed record<br />
attribute: THandle;<br />
pData: Pointer;<br />
dataSize: ULONG;<br />
end;<br />
<br />
<br />
var<br />
Form1: TForm1;<br />
<br />
var<br />
SetWindowCompositionAttribute: function (Wnd: HWND; const AttrData: TWinCompAttrData): BOOL; stdcall = Nil;<br />
implementation<br />
<br />
{$R *.lfm}<br />
<br />
procedure SetAlphaColorPicture(<br />
const Col: TColor;<br />
const Alpha: Integer;<br />
Picture: TPicture;<br />
const _width: Integer;<br />
const _height: Integer<br />
);<br />
var<br />
IM: TLazIntfImage;<br />
x,y: integer;<br />
sl: pByteArray;<br />
I, J, W, H: Integer;<br />
FC: TFPColor;<br />
begin<br />
IM := TLazIntfImage.Create(0, 0, [riqfRGB, riqfAlpha]);<br />
try<br />
IM.SetSize(_width, _height);<br />
for I := 0 to _width - 1 do<br />
begin<br />
for J := 0 to _height - 1 do<br />
begin<br />
FC.red := (128 + I) shl 8;<br />
FC.green := (128 + J) shl 8;<br />
FC.blue := 128 shl 8;<br />
FC.alpha := 128 shl 8; // now works fine<br />
IM.Colors[I, J] := FC;<br />
end;<br />
end;<br />
Picture.Assign(IM);<br />
<br />
<br />
finally<br />
IM.Free;<br />
<br />
end;<br />
end;<br />
<br />
procedure TForm1.Button1Click(Sender: TObject);<br />
begin<br />
Close;<br />
end;<br />
<br />
procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;<br />
Shift: TShiftState; X, Y: Integer);<br />
begin<br />
ReleaseCapture;<br />
SendMessage(Form1.Handle, LM_SYSCOMMAND, 61458, 0) ;<br />
end;<br />
<br />
procedure TForm1.AeroGlass;<br />
var<br />
Aero: BOOL;<br />
Area: TRect;<br />
hDWM: THandle;<br />
begin<br />
hDWM:=LoadLibrary('dwmapi.dll');<br />
try<br />
@DwmIsCompositionEnabled:=GetProcAddress(hDWM,'DwmIsCompositionEnabled');<br />
if @DwmIsCompositionEnabled<>nil then<br />
DwmIsCompositionEnabled(Aero);<br />
if Aero then<br />
begin<br />
Area:=Rect(-1,-1,-1,-1);<br />
Color:=clBlack;<br />
@DwmExtendFrameIntoClientArea:=GetProcAddress(hDWM,'DwmExtendFrameIntoClientArea');<br />
if @DwmExtendFrameIntoClientArea<>nil then<br />
DwmExtendFrameIntoClientArea(Handle,@Area);<br />
<br />
end<br />
else ShowMessage('Aero is Disabled');<br />
finally<br />
FreeLibrary(hDWM);<br />
end;<br />
end;<br />
<br />
procedure TForm1.EnableBlur;<br />
const<br />
WCA_ACCENT_POLICY = 19;<br />
ACCENT_ENABLE_BLURBEHIND = 3;<br />
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4;<br />
DrawLeftBorder = $20;<br />
DrawTopBorder = $40;<br />
DrawRightBorder = $80;<br />
DrawBottomBorder = $100;<br />
var<br />
dwm10: THandle;<br />
data : TWinCompAttrData;<br />
accent: AccentPolicy;<br />
begin<br />
<br />
dwm10 := LoadLibrary('user32.dll');<br />
try<br />
@SetWindowCompositionAttribute := GetProcAddress(dwm10, 'SetWindowCompositionAttribute');<br />
if @SetWindowCompositionAttribute <> nil then<br />
begin<br />
accent.AccentState := ACCENT_ENABLE_BLURBEHIND ;<br />
//accent.AccentState := ACCENT_ENABLE_ACRYLICBLURBEHIND;<br />
accent.GradientColor := (100 SHL 24) or ($00E3E0DE);<br />
accent.AccentFlags := DrawLeftBorder or DrawTopBorder or DrawRightBorder or DrawBottomBorder;<br />
<br />
data.Attribute := WCA_ACCENT_POLICY;<br />
data.dataSize := SizeOf(accent);<br />
data.pData := @accent;<br />
SetWindowCompositionAttribute(self.Handle, data);<br />
end<br />
else<br />
begin<br />
ShowMessage('Not found Windows 10 blur API');<br />
end;<br />
finally<br />
FreeLibrary(dwm10);<br />
end;<br />
<br />
end;<br />
<br />
procedure TForm1.FormCreate(Sender: TObject);<br />
begin<br />
DoubleBuffered := True;<br />
Color := clBlack;<br />
BorderStyle := bsnoNe;<br />
BorderIcons := [biSystemMenu, biMinimize, biMaximize];<br />
//AeroGlass;<br />
if TaskbarTranslucent then<br />
EnableBlur;<br />
<br />
UpdateColorization;<br />
end;<br />
<br />
procedure TForm1.BCButtonFocus1Click(Sender: TObject);<br />
begin<br />
close;<br />
end;<br />
<br />
function TForm1.TaskbarAccented: boolean;<br />
var<br />
reg: TRegistry;<br />
begin<br />
Result := False;<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CURRENT_USER;<br />
reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize');<br />
try<br />
if reg.ReadInteger('ColorPrevalence') = 1 then<br />
Result := True;<br />
except<br />
Result := False;<br />
end;<br />
reg.CloseKey;<br />
<br />
finally<br />
reg.Free;<br />
end;<br />
end;<br />
<br />
function TForm1.TaskbarTranslucent: boolean;<br />
var<br />
reg: TRegistry;<br />
begin<br />
Result := False;<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CURRENT_USER;<br />
reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize');<br />
try<br />
if reg.ReadInteger('EnableTransparency') = 1 then<br />
Result := True;<br />
except<br />
Result := False;<br />
end;<br />
reg.CloseKey;<br />
<br />
finally<br />
reg.Free;<br />
end;<br />
end;<br />
<br />
<br />
<br />
procedure TForm1.UpdateColorization;<br />
begin<br />
if TaskbarTranslucent then<br />
begin<br />
SetAlphaColorPicture(clblack, 200, Image1.Picture, 10,10 );<br />
Image1.Align := alClient;<br />
Image1.Stretch := True;<br />
Image1.Visible := True;<br />
end<br />
else<br />
Image1.Visible := False;<br />
<br />
if TaskbarAccented then<br />
begin<br />
SetAlphaColorPicture(9338482, 110, Image2.Picture, 10, 10);<br />
Image2.Visible := True;<br />
Image2.Align := alClient;<br />
Image2.Stretch := True;<br />
end<br />
else<br />
Image2.Visible := False;<br />
end;<br />
<br />
function TForm1.GetAccentColor:TColor;<br />
var<br />
col: cardinal;<br />
opaque: longbool;<br />
newcolor: TColor;<br />
a,r,g,b: byte;<br />
begin<br />
DwmGetColorizationColor(col, opaque);<br />
a := Byte(col shr 24);<br />
r := Byte(col shr 16);<br />
g := Byte(col shr 8);<br />
b := Byte(col);<br />
<br />
<br />
newcolor := RGB(<br />
round(r*(a/255)+255-a),<br />
round(g*(a/255)+255-a),<br />
round(b*(a/255)+255-a)<br />
);<br />
<br />
Result := newcolor;<br />
<br />
<br />
end;<br />
<br />
<br />
initialization<br />
SetWindowCompositionAttribute := GetProcAddress(GetModuleHandle(user32), 'SetWindowCompositionAttribute');<br />
end.<br />
</syntaxhighlight><br />
<br />
== Bugs ==<br />
<br />
As you can see in the first image Labels aren't displayed fine in Aero Glass, there are links with components and code that show how to make "Glow Labels":<br />
<br />
*[http://development.mwcs.de/glowlabel.html GlowLabel for Delphi]<br />
*[http://www.delphipraxis.net/953968-post4.html Aero Glass - ein Text (Label) hintergrund "machen"]<br />
<br />
Also if you clic the transparent part of the window the back window / desktop is selected (focus is lost in the form with aero glass).<br />
<br />
== About ==<br />
<br />
This was converted to Lazarus using "{$mode delphi}" from "Aero Glass Effekt für Delphi-Forms, Delphi-Unit von Daniel Mitte (2006)":<br />
<br />
*[http://www.delphipraxis.net/74538-aero-glass-effekt-fuer-delphi-forms.html Aero Glass Effekt für Delphi-Forms]<br />
<br />
There is a Delphi component here (to be ported in Lazarus):<br />
<br />
*[http://www.torry.net/authorsmore.php?id=6179 D. Mitte in Torry's Delphi Page]<br />
<br />
[[Category:Tutorials]]<br />
[[Category:Windows]]</div>007https://wiki.freepascal.org/index.php?title=Streaming_JSON&diff=137056Streaming JSON2020-06-07T23:39:08Z<p>007: Adding custom properties</p>
<hr />
<div>{{Streaming JSON}}<br />
<br />
[[JSON]] (JavaScript Object Notation) is a text-based, standardized data format. As the name implies, JSON documents are valid JavaScript code and can be directly converted into JavaScript objects. However, JSON can be used for data exchange regardless of the programming language used.<br />
<br />
This tutorial explains how to load JSON data into a Free Pascal program and process it there. It also explains how to convert data from the program into JSON (eg to send it to a web browser).<br />
<br />
== General requirements ==<br />
<br />
Loading and storing (streaming) objects is done with the fpjsonrtti unit. It also makes sense to use the Classes unit (see below for details).<br />
<br />
The uses statement should therefore contain at least these two units:<br />
<br />
<syntaxhighlight lang=pascal><br />
uses Classes, fpjsonrtti;<br />
</syntaxhighlight><br />
<br />
Currently (May 2014) there are some differences between Free Pascal's streaming system and JSON:<br />
<br />
* JSON is a case-sensitive data format. It follows that the properties of the Free Pascal objects must be written in the same case as the JSON properties.<br />
* No properties can be defined with DefineProperties. No references to methods (event handlers) can be saved.[[#ref2|<sup>2</sup>]]<br />
* [[TCollection]] and [[TStrings]] can used as a replacements for arrays.<br />
<br />
Demo programs are provided with Free Pascal Compiler source code in the <tt>packages/fcl-json/examples</tt> directory.<br />
<br />
This JSON structure is used in the examples which follow:<br />
<br />
<syntaxhighlight lang="JavaScript"><br />
{<br />
"id" : 123, // an integer<br />
"obj" : { "name": "Hello world!" }, // an object<br />
"coll" : [ { "name": "Object 1" }, { "name": "Object 2" } ], // two objects in a TCollection<br />
"strings": [ "Hello 1", "Hello 2" ] // a string list<br />
}<br />
</syntaxhighlight><br />
<br />
It can be defined in your Free Pascal program using a constant assignment as follows:<br />
<br />
<syntaxhighlight lang=pascal><br />
const JSON_TESTDATA =<br />
'{'+LineEnding+<br />
' "id": 123,'+LineEnding+<br />
' "obj": { "name": "Hello world!" },'+LineEnding+<br />
' "coll": [ { "name": "Object 1" }, { "name": "Object 2" } ],'+LineEnding+<br />
' "strings": [ "Hello 1", "Hello 2" ]'+LineEnding+<br />
'}';<br />
</syntaxhighlight><br />
<br />
== Data Structure ==<br />
<br />
The base class for the data is [[TPersistent]] from the Classes unit, [[Runtime Type Information (RTTI)|runtime type information (RTTI)]] is created for it and all subclasses. These are essential for streaming. Since fpjsonrtti does not integrate into the streaming system, any other class translated with the compiler switch '''{$M+}''' can also be used.<br />
<br />
All properties to be read must be declared as a [[Property|property]] in the [[Published|published]] section of the class. As a rule, you can use read and write to refer directly to a data field (the variable). If you want, you can of course use getter and setter methods.<br />
<br />
The following class definition results from the JSON structure:<br />
<br />
<syntaxhighlight lang=pascal><br />
type<br />
TNameObject = class(TCollectionItem) // class for the 'obj' property and TCollection <br />
private<br />
fName: String;<br />
published<br />
property name: String read fName write fName;<br />
end; <br />
<br />
TBaseObject = class(TPersistent) // class for the entire JSON structure<br />
private<br />
fid: Integer;<br />
fObj: TNameObject;<br />
fColl: TCollection;<br />
fStrings: TStrings;<br />
public<br />
constructor Create;<br />
destructor Destroy; override;<br />
published // all properties must be published <br />
property id: Integer read fid write fid;<br />
property obj: TNameObject read fObj write fObj;<br />
property coll: TCollection read fColl;<br />
property strings: TStrings read fStrings;<br />
end; <br />
</syntaxhighlight><br />
<br />
The <syntaxhighlight enclose="none" lang=pascal>TNameObject</syntaxhighlight> class was derived from [[TCollectionItem]]. This means that it can be used both for the obj property and in the collection. If this is not desired, then two different classes must be defined here.<br />
<br />
The TCollection and the string list must be created in the constructor of the TBaseObject class and released in the destructor.<br />
<br />
<syntaxhighlight lang=pascal><br />
constructor TBaseObject.Create;<br />
begin<br />
// Create Collection and StringList<br />
fColl := TCollection.Create(TNameObject);<br />
fStrings := TStringList.Create;<br />
fObj := TNameObject.Create(nil);<br />
end;<br />
<br />
destructor TBaseObject.Destroy;<br />
begin<br />
// Release Collection and StringList<br />
fColl.Free;<br />
fStrings.Free;<br />
fObj.Free;<br />
inherited Destroy;<br />
end;<br />
</syntaxhighlight><br />
<br />
If you do not want any more functionality in the data classes, their definition is now complete.<br />
<br />
== Load JSON ==<br />
<br />
With the method <syntaxhighlight enclose="none" lang=pascal>Procedure JSONToObject(Const JSON : TJSONStringType; AObject : TObject);</syntaxhighlight> in the [[TJSONDeStreamer]] class you can assign JSON data directly to an ''existing'' object. Before you call the method, you must create TJSONDeStreamer and the target object.<br />
<br />
The following method loads the data from the JSON structure <syntaxhighlight enclose="none" lang=pascal>JSON_TESTDATA</syntaxhighlight> in the object o and then outputs the current values of the properties to the console.<br />
<br />
<syntaxhighlight lang=pascal><br />
procedure DeStreamTest;<br />
var<br />
DeStreamer: TJSONDeStreamer;<br />
o: TBaseObject;<br />
no: TNameObject;<br />
s: String;<br />
begin<br />
WriteLn('DeStream test');<br />
WriteLn('======================================');<br />
<br />
// Create the DeStreamer object and target object<br />
DeStreamer := TJSONDeStreamer.Create(nil);<br />
o := TBaseObject.Create;<br />
try<br />
// Load JSON data into object o<br />
DeStreamer.JSONToObject(JSON_TESTDATA, o);<br />
// output ID<br />
WriteLn(o.id);<br />
// output object name<br />
WriteLn(o.obj.name); <br />
// output the names of all objects<br />
for TCollectionItem(no) in o.coll do<br />
Writeln(no.name);<br />
// output all strings<br />
for s in o.strings do<br />
WriteLn(s);<br />
<br />
// Cleanup<br />
finally<br />
o.Destroy;<br />
DeStreamer.Destroy;<br />
end;<br />
end;<br />
</syntaxhighlight><br />
<br />
== Saving JSON ==<br />
<br />
The class [[TJSONStreamer]] is used to convert an object into JSON text. Here the method <syntaxhighlight enclose="none" lang=pascal>Function ObjectToJSONString(AObject : TObject) : TJSONStringType;</syntaxhighlight> is used.<br />
<br />
In the following procedure, an object is created, filled with the test data, and then converted to JSON. The JSON text is output on the console. The order in which the properties are output cannot be specified.<br />
<br />
<syntaxhighlight lang=pascal><br />
procedure StreamTest;<br />
var<br />
Streamer: TJSONStreamer;<br />
o: TBaseObject;<br />
JSONString: String;<br />
begin<br />
WriteLn('Stream test');<br />
WriteLn('======================================');<br />
<br />
Streamer := TJSONStreamer.Create(nil);<br />
o := TBaseObject.Create;<br />
try<br />
// Setup data<br />
o.id := 123;<br />
o.obj.name := 'Hello world!';<br />
TNameObject(o.coll.Add).name := 'Object 1';<br />
TNameObject(o.coll.Add).name := 'Object 2';<br />
o.strings.Add('Hello 1');<br />
o.strings.Add('Hello 2');<br />
<br />
Streamer.Options := Streamer.Options + [jsoTStringsAsArray]; // Save strings as JSON array<br />
// convert to JSON and output to console<br />
JSONString := Streamer.ObjectToJSONString(o);<br />
WriteLn(JSONString);<br />
<br />
// Cleanup<br />
finally<br />
o.Destroy;<br />
Streamer.Destroy;<br />
end;<br />
end;<br />
</syntaxhighlight><br />
<br />
== Custom properties ==<br />
<br />
Now that we can save and load to JSON, we can as well customize how the property is saved. By default a TColor (TGraphicsColor) is saved as a number, but for example we want to make it a string, so is more human readable.<br />
<br />
This example uses BGRABitmap library, that has a function to convert from string to color easily. The streamed control in this case is a button control from BGRAControls package.<br />
<br />
This customizes how TColor is saved and loaded.<br />
<br />
Saving code:<br />
<br />
<syntaxhighlight lang=pascal><br />
procedure TForm1.Button1Click(Sender: TObject);<br />
var<br />
Streamer: TJSONStreamer;<br />
JSONString: String;<br />
begin<br />
Streamer := TJSONStreamer.Create(nil);<br />
try<br />
Streamer.OnStreamProperty:=@OnStreamProperty;<br />
JSONString := Streamer.ObjectToJSONString(BCButton1.StateNormal);<br />
Memo1.Lines.Text := JSONString;<br />
finally<br />
Streamer.Destroy;<br />
end;<br />
end;<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=pascal><br />
procedure TForm1.OnStreamProperty(Sender: TObject; AObject: TObject;<br />
Info: PPropInfo; var Res: TJSONData);<br />
var<br />
bgracolor: TBGRAPixel;<br />
begin<br />
if (Info^.PropType^.Name = 'TGraphicsColor') then<br />
begin<br />
bgracolor := ColorToBGRA(TColor(GetPropValue(AObject, Info, False)));<br />
Res.Free;<br />
Res := TJSONString.Create('rgb('+IntToStr(bgracolor.red)+','+IntToStr(bgracolor.green)+','+IntToStr(bgracolor.blue)+')');<br />
end;<br />
end; <br />
</syntaxhighlight><br />
<br />
Loading code:<br />
<br />
<syntaxhighlight lang=pascal><br />
procedure TForm1.Button2Click(Sender: TObject);<br />
var<br />
DeStreamer: TJSONDeStreamer;<br />
s: String;<br />
begin<br />
DeStreamer := TJSONDeStreamer.Create(nil);<br />
try<br />
DeStreamer.OnRestoreProperty:=@OnRestoreProperty;<br />
DeStreamer.JSONToObject(Memo1.Lines.Text, BCButton1.StateNormal);<br />
finally<br />
DeStreamer.Destroy;<br />
end;<br />
end;<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=pascal><br />
procedure TForm1.OnRestoreProperty(Sender: TObject; AObject: TObject;<br />
Info: PPropInfo; AValue: TJSONData; var Handled: Boolean);<br />
var<br />
bgracolor: TBGRAPixel;<br />
begin<br />
Handled := False;<br />
if (Info^.PropType^.Name = 'TGraphicsColor') then<br />
begin<br />
Handled := True;<br />
bgracolor := StrToBGRA(AValue.AsString);<br />
SetPropValue(AObject, Info, BGRAToColor(bgracolor));<br />
end;<br />
end;<br />
</syntaxhighlight><br />
<br />
== Conclusion ==<br />
<br />
With the knowledge presented, simple and complex JSON data structures can be loaded into Free Pascal programs. Should any pre- or post-processing of the JSON data be necessary, the text data can be first loaded from the [[jsonparser]] unit into a JSON data structure using the [[TJSONParser]] class and then manipulated as desired with the [[fpJSON]] unit.<br />
<br />
The Options property of the TJSONStreamer class can be used to control how the output maps its own data structures in JSON.<br />
<br />
== See Also ==<br />
<br />
* [[JSON]]<br />
* [[fcl-json]]<br />
* [[Streaming components]]<br />
<br />
== Notes & References ==<br />
<br />
# <div id="ref1">http://lists.freepascal.org/fpc-pascal/2013-January/036254.html</div><br />
# <div id="ref2>http://lists.lazarus.freepascal.org/pipermail/lazarus/2011-January/058878.html</div></div>007https://wiki.freepascal.org/index.php?title=BGRASpriteAnimation&diff=135175BGRASpriteAnimation2020-04-03T21:23:06Z<p>007: </p>
<hr />
<div>{{BGRASpriteAnimation}}<br />
<br />
== Overview ==<br />
<br />
[[BGRASpriteAnimation]] is a graphic control developed with the [[BGRABitmap]] library. It is part of the [[BGRAControls]] package. This control is usefull to create animations from bitmaps.<br />
<br />
To use as replace of TImage just turn on the option 'AnimStatic' and you'll be able to load single images.<br />
<br />
== Beginning ==<br />
<br />
Add a new BGRASpriteAnimation from the "BGRA Controls" component tab.<br />
<br />
The next step is to load a "sprite". A sprite is a bitmap that contains all the frames of an animation. To load a sprite select "BGRASpriteAnimation1". In the Object Inspector click on the property "Sprite (TBitmap)[...]". Load the sprite the same way as you load any other bitmap.<br />
<br />
This is the sprite we will use to explain how the component works:<br />
<br />
[[Image:bgraspriteanimation_main_sprite.png]]<br />
<br />
We can say the sprite dimensions are 100x500 px. It has 5 frames, so each frame is 100x100 px.<br />
<br />
The next step is to tell the component that the sprite has 5 frames. To set the number of frames in the Object Inspector click on the property "SpriteCount" and set the value to 5.<br />
<br />
Now you can run the application and see the resulting animation.<br />
<br />
== Animation ==<br />
<br />
The animation properties are AnimInvert, AnimPosition, AnimRepeat, AnimRepeatLap, AnimSpeed & AnimStatic.<br />
<br />
'''AnimInvert:''' By default the animation is played from AnimPosition to SpriteCount. If you set AnimInvert to True the animation will be played inversely, that is from the last frame to the first.<br />
<br />
'''AnimPosition:''' The position of the frame in the animation.<br />
<br />
'''AnimRepeat:''' The number of times the animation will be played. Set 0 for infinite.<br />
<br />
'''AnimRepeatLap:''' The number of times the animation was played. If it reaches the value of AnimRepeat the animation will stop.<br />
<br />
'''AnimSpeed:''' The speed in milliseconds between frames.<br />
<br />
'''AnimStatic:''' Use to start & stop the animation.<br />
<br />
== Sprite ==<br />
<br />
The sprite properties are Sprite, SpriteCount, SpriteFillOpacity, SpriteFlipMode, SpriteKeyColor, SpriteResampleFilter, SpriteResampleMode, SpriteRotation.<br />
<br />
'''Sprite:''' A bitmap that contains all the frames of the animation.<br />
<br />
'''SpriteCount:''' A number that indicates the amount of frames of the sprite.<br />
<br />
The following properties are sprite modifications.<br />
<br />
'''SpriteFillOpacity:''' The amount of opacity from 0 to 255.<br />
<br />
'''SpriteFlipMode:''' Flip none, horizontal, vertical or both. <br />
<br />
'''SpriteKeyColor:''' The color that will be replaced with transparency.<br />
<br />
'''SpriteResampleFilter:''' The filter that will be used on resizing.<br />
<br />
'''SpriteResampleMode:''' If you choose FineResample the selected resample filter will be used.<br />
<br />
'''SpriteRotation:''' Rotation none, clockwise, counterclockwise.<br />
<br />
== Events ==<br />
<br />
OnRedrawBefore, OnRedrawAfter, OnPositionChanging, OnPositionChanged, OnLapChanging, OnLapChanged in that order.<br />
<br />
The following events are specific to sprites.<br />
<br />
'''OnRedrawBefore:''' This fires before applying the sprite modifications.<br />
<br />
'''OnRedrawAfter:''' This fires after applying the sprite modifications, but before applying resample.<br />
<br />
The following events are specific to animation.<br />
<br />
'''OnPositionChanging:''' This fires before the animation changes the AnimPosition value.<br />
<br />
'''OnPositionChanged:''' This fires when the AnimPosition value has changed (by the animation or by the user).<br />
<br />
'''OnLapChanging:''' This fires before the animation changes the AnimRepeatLap value.<br />
<br />
'''OnLapChanged:''' This fires when the AnimRepeatLap value has changed (by the animation or by the user).<br />
<br />
== How to Create Sprites? ==<br />
<br />
Most Graphics software (Gimp, Photoshop) can create Animations as Image Sequences. In Windows you can use IrfanView's (Freeware) panoramamode to Join these Images into a sprite. (Image> Create Panorama Image…)<br />
<br />
== How to load images with mutiple rows? ==<br />
<br />
Check this forum post attachment https://forum.lazarus.freepascal.org/index.php/topic,49164.msg355639.html#msg355639<br />
<br />
[[Category: Graphics]] [[Category: Components]]<br />
[[Category:BGRAControls]]</div>007https://wiki.freepascal.org/index.php?title=BGRABitmap_tutorial_1&diff=130204BGRABitmap tutorial 12019-12-31T14:19:56Z<p>007: /* Create a new project */</p>
<hr />
<div>{{BGRABitmap_tutorial_1}}<br />
<br />
{{BGRABitmap_tutorial_index}}<br />
<br />
This first tutorial shows you how to use [[BGRABitmap]] library.<br />
<br />
You can download the library on [https://github.com/bgrabitmap GitHub].<br />
<br />
=== Create a new project ===<br />
<br />
Create an windowed application with menu '''Project > New project'''.<br />
<br />
The main form unit should look like this:<br />
<syntaxhighlight>unit UMain;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs;<br />
<br />
type<br />
<br />
{ TForm1 }<br />
<br />
TForm1 = class(TForm)<br />
private<br />
{ private declarations }<br />
public<br />
{ public declarations }<br />
end; <br />
<br />
var<br />
Form1: TForm1; <br />
<br />
implementation<br />
<br />
initialization<br />
{$I UMain.lrs}<br />
<br />
end.</syntaxhighlight><br />
<br />
If you do not find it, use '''Ctrl-F12''' to show file list.<br />
<br />
Save your project next to BGRABitmap library with menu '''File > Save all''' (not necessarily in the same folder).<br />
<br />
=== Add reference to BGRABitmap ===<br />
<br />
The first time you use BGRABitmap, open bgrabitmappack.lpk with Lazarus and click on "Use > Add to Project". Then, if you need to add the reference in another project, you can do it through the Project inspector and click on "Add... > New condition" and choose BGRABitmapPack.<br />
<br />
In the unit clause, add a reference to BGRABitmap and BGRABitmapTypes after Dialogs.<br />
<br />
<syntaxhighlight>uses<br />
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,<br />
BGRABitmap, BGRABitmapTypes;</syntaxhighlight><br />
<br />
==== Alternative ways of referencing ====<br />
<br />
===== By installing BGRABitmap package =====<br />
<br />
Open bgrabitmappack.lpk as a package. Make sure it is possible to install it by going in the package window into "Options > IDE Integration" and setting the package type to "designtime and runtime". Then in the package window, click on install. A dialog pops up, asking if the package must be added to Lazarus and if it needs to be compiled again. Choose Yes twice.<br />
<br />
If everything is fine, Lazarus restarts and BGRABitmap units are available. If it does not work, you can simply add BGRABitmap to the search path without compiling Lazarus.<br />
<br />
===== By adding BGRABitmap units to the search path =====<br />
<br />
Another way is to add BGRABitmap units to the search path of the project. To do this, go to compiler options with menu '''Project > Compiler options'''. In other unit files path, add the relative path to BGRABitmap. For example, if BGRABitmap is in a folder next to your project, the relative path could be "..\BGRABitmap".<br />
<br />
If you copy BGRABitmap files in the same folder as your project, then you do not need to add such search path. However, it is not recommended because if you have multiple projects using the library, it could become a repetitive task to update to a new version of the library.<br />
<br />
If you are lost with relative path, you can also add the relative path by adding the BGRABitmap unit to your project. To do so, open within your project the file bgrabitmap.pas. Then use menu '''Project > Add file to project'''. Lazarus will ask if you want to add the file and the new directory to the project.<br />
<br />
=== Add some drawing ===<br />
<br />
Add a painting event. To do this, click on the form, then go to the object inspector, in the event tab, and double click on the OnPaint line. Lazarus will add automatically a FormPaint handler to the main form unit. Add for example the following code inside it :<br />
<syntaxhighlight>procedure TForm1.FormPaint(Sender: TObject);<br />
var bmp: TBGRABitmap;<br />
begin<br />
bmp := TBGRABitmap.Create(ClientWidth, ClientHeight, BGRABlack);<br />
bmp.FillRect(20, 20, 100, 40, BGRA(255,192,0), dmSet); //fill an orange rectangle<br />
bmp.Draw(Canvas, 0, 0, True); //render BGRABitmap on the form<br />
bmp.Free; //free memory<br />
end;</syntaxhighlight><br />
<br />
As you can see, you need to define a [[TBGRABitmap class|TBGRABitmap]] variable and create it. There are several constructors for [[TBGRABitmap class|TBGRABitmap]]. The one used here creates a bitmap of size ClientWidth x ClientHeight and filled with black. ClientWidth and ClientHeight are form properties that return the available space for drawing inside the form.<br />
<br />
The FillRect procedure takes usual parameters for drawing a rectangle, that is the upper-left corner followed by the lower-right corner plus 1. It means that the pixel at (100,40) is excluded from the rectangle.<br />
<br />
After that, there is a color parameter with red/green/blue components, and a drawing mode. dmSet means to simply replace the pixels.<br />
<br />
Do not forget to free the object after using it, to avoid a memory leak.<br />
<br />
=== Resulting code ===<br />
<br />
You should obtain the following code:<br />
<syntaxhighlight>unit UMain;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,<br />
BGRABitmap, BGRABitmapTypes;<br />
<br />
type<br />
<br />
{ TForm1 }<br />
<br />
TForm1 = class(TForm)<br />
procedure FormPaint(Sender: TObject);<br />
private<br />
{ private declarations }<br />
public<br />
{ public declarations }<br />
end; <br />
<br />
var<br />
Form1: TForm1; <br />
<br />
implementation<br />
<br />
{ TForm1 }<br />
<br />
procedure TForm1.FormPaint(Sender: TObject);<br />
var bmp: TBGRABitmap;<br />
begin<br />
bmp := TBGRABitmap.Create(ClientWidth,ClientHeight,BGRABlack);<br />
bmp.FillRect(20,20,100,40,BGRA(255,192,0),dmSet);<br />
bmp.Draw(Canvas,0,0,True);<br />
bmp.Free;<br />
end;<br />
<br />
initialization<br />
{$I UMain.lrs}<br />
<br />
end.</syntaxhighlight><br />
<br />
=== Run the program ===<br />
<br />
You should obtain a window filled in black with an orange rectangle in it.<br />
<br />
[[Image:BGRATutorial1.png]]<br />
<br />
[[BGRABitmap tutorial 2|Go to next tutorial (image loading)]]<br />
<br />
[[Category:Graphics]]<br />
[[Category: BGRABitmap]]</div>007https://wiki.freepascal.org/index.php?title=BGRAControls&diff=130156BGRAControls2019-12-28T13:40:54Z<p>007: </p>
<hr />
<div>{{BGRAControls}}<br />
<br />
[[File:bgracontrols.png]]<br />
<br />
= Install =<br />
<br />
Use the [[Online Package Manager]] to get BGRABitmap and BGRAControls.<br />
<br />
Notice that you must check only the packages "bgrabitmappack.lpk" and "bgracontrols.lpk" in the Online Package Manager. The other packages are optional and may need third party packages / libraries to work (OpenGL and PascalScript).<br />
<br />
== Optional Components ==<br />
<br />
Since v4.4 the components TBCDefaultThemeManager, TBCKeyboard and TBCNumericKeyboard are not installed by default to allow Linux users to get a seamless installation with the Online Package Manager not installing third party stuff. If you want these components turn on the "Register unit" in the package options for each file (bcdefaulthememanager.pas, bckeyboard.pas, bcnumerickeyboard.pas) then compile and rebuild Lazarus. On Linux you need to install libxtst-dev and libgl-dev first.<br />
<br />
== Website ==<br />
<br />
BGRABitmap Organization on GitHub: https://github.com/bgrabitmap/<br />
<br />
= BGRA Controls =<br />
<br />
BGRA Controls is a set of graphical UI elements that you can use with Lazarus LCL applications.<br />
Under Linux you need to have installed libxtst-dev and libgl-dev.<br />
<br />
=== TBCButton ===<br />
<br />
[[Image:bcbutton.png]]<br />
<br />
A button control that can be styled through properties for each state like StateClicked, StateHover, StateNormal with settings like gradients, border and text with shadows. You can assign an already made style through the property AssignStyle.<br />
<br />
=== TBCButtonFocus ===<br />
<br />
Like TBCButton but it supports focus like normal TButton.<br />
<br />
=== TBCGameGrid ===<br />
<br />
[[Image:bcgamegrid.png]]<br />
<br />
A grid with custom width and height of items and any number of horizontal and vertical cells that can be drawn with BGRABitmap directly with the OnRenderControl event.<br />
<br />
=== TBCImageButton ===<br />
<br />
[[Image:samplebgraimagebutton.png]]<br />
<br />
[[Image:samplebgraimagebuttonalpha.png]]<br />
<br />
A button control that can be styled with one image file, containing the drawing for each state Normal, Hovered, Active and Disabled. It supports 9-slice scaling feature. It supports a nice fading animation that can be turned on.<br />
<br />
=== TBCXButton ===<br />
<br />
[[Image:bcxbutton.png]]<br />
<br />
A button control that can be styled by code with the OnRenderControl event. Or even better create your own child control inheriting from this class.<br />
<br />
=== TBCLabel ===<br />
<br />
[[Image:bclabel.png]]<br />
<br />
A label control that can be styled through properties, it supports shadow, custom borders and background.<br />
<br />
=== TBCMaterialDesignButton ===<br />
<br />
A button control that has an animation effect according to Google Material Design guidelines. It supports custom color for background and for the circle animation, also you can customize the shadow.<br />
<br />
=== TBCPanel ===<br />
<br />
[[Image:bcpanel.png]]<br />
<br />
A panel control that can be styled through properties. You can assign an already made style through the property AssignStyle.<br />
<br />
=== TBCRadialProgressBar ===<br />
<br />
A progress bar with radial style. You can set the color and text properties as you like.<br />
<br />
=== TBCToolBar ===<br />
<br />
A TToolBar with an event OnRedraw to paint it using BGRABitmap. It supports also the default OnPaintButton to customize the buttons drawing. By default it comes with a Windows 7 like explorer toolbar style.<br />
<br />
=== TBCTrackBarUpdown ===<br />
<br />
A control to input numeric values with works like a trackbar and a spinedit both in one control.<br />
<br />
=== TBGRAFlashProgressBar ===<br />
<br />
[[Image:BC-Bgraflashprogressbar.png]]<br />
<br />
A progress bar with a default style inspired in the old Flash Player Setup for Windows progress dialog. You can change the color property to have different styles and also you can use the event OnRedraw to paint custom styles on it like text or override the entire default drawing.<br />
<br />
=== TBGRAGraphicControl ===<br />
<br />
Is like a paintbox. You can draw with transparency with this control using the OnRedraw event.<br />
<br />
=== TBGRAImageList ===<br />
<br />
[[Image:before-TImageList.png]]<br />
<br />
[[Image:after-TBGRAImageList.png]]<br />
<br />
An image list that supports alpha in all supported platforms.<br />
<br />
=== TBGRAImageManipulation ===<br />
<br />
[[Image:bgraimagemanipulation.jpg]]<br />
<br />
A tool to manipulate pictures, see the demo that shows all the capability that comes with it.<br />
<br />
=== TBGRAKnob ===<br />
<br />
[[Image:BC-Bgraknob.png]]<br />
<br />
A knob that can be styled through properties.<br />
<br />
=== TBGRAResizeSpeedButton ===<br />
<br />
A speed button that can resize the glyph to fit in the entire control.<br />
<br />
=== TBGRAShape ===<br />
<br />
[[Image:samplebgrashape.png]]<br />
<br />
A control with configurable shapes like polygon and ellipse that can be filled with gradients and can have custom borders and many other visual settings.<br />
<br />
=== TBGRASpeedButton ===<br />
<br />
[[Image:BGRASpeedButton.png]]<br />
<br />
A speed button that in GTK and GTK2 provides BGRABitmap powered transparency to the glyph.<br />
<br />
=== TBGRASpriteAnimation ===<br />
<br />
[[Image:bgraspriteanimation.png]]<br />
<br />
A component that can be used as image viewer or animation viewer, supports the loading of gif files.<br />
<br />
=== TBGRAVirtualScreen ===<br />
<br />
Is like a panel. You can draw this control using the OnRedraw event.<br />
<br />
=== TDTAnalogClock ===<br />
<br />
A clock.<br />
<br />
=== TDTAnalogGaugue ===<br />
<br />
A gauge.<br />
<br />
=== TDTThemedClock ===<br />
<br />
Another clock.<br />
<br />
=== TDTThemedGauge ===<br />
<br />
Another gauge.<br />
<br />
=== TPSImport_BGRAPascalScript ===<br />
<br />
A component to load BGRABitmap pascal script utilities.<br />
<br />
= BGRA Custom Drawn =<br />
<br />
BGRA Custom Drawn is a set of controls inherited from Custom Drawn. These come with a default dark style that is like Photoshop.<br />
<br />
=== TBCDButton ===<br />
<br />
A button control that is styled with TBGRADrawer.<br />
<br />
=== TBCDEdit ===<br />
<br />
An edit control that is styled with TBGRADrawer.<br />
<br />
=== TBCDStaticText ===<br />
<br />
A label control that is styled with TBGRADrawer.<br />
<br />
=== TBCDProgressBar ===<br />
<br />
A progress bar control that is styled with TBGRADrawer.<br />
<br />
=== TBCDSpinEdit ===<br />
<br />
A spin edit control that is styled with TBGRADrawer.<br />
<br />
=== TBCDCheckBox ===<br />
<br />
A check box control that is styled with TBGRADrawer.<br />
<br />
=== TBCRadioButton ===<br />
<br />
A radio button that is styled with TBGRADrawer.<br />
<br />
= Sample code =<br />
<br />
BGRA Controls comes with nice demos to show how to use the stuff and extra things you can use in your own projects.<br />
<br />
=== Pascal Script Library ===<br />
<br />
Putting BGRABitmap methods into a .dll with c#, java and pascal headers.<br />
<br />
=== BGRA Ribbon Custom ===<br />
<br />
How to create a fully themed window using the controls to achieve a Ribbon like application.<br />
<br />
=== Tests ===<br />
<br />
There are test for analog controls (clock and gauge), BC prefixed controls, BGRA prefixed controls, BGRA Custom Drawn controls, how to use Pascal Script and BGRABitmap, bgrascript or how to create your own scripting solution with BGRABitmap.<br />
<br />
=== Tests Extra ===<br />
<br />
[[Image:game_maze.png]]<br />
<br />
[[Image:game_puzzle.png]]<br />
<br />
[[Image:customdrawnwindows7.png]]<br />
<br />
[[File:slicescaledtachart.png]]<br />
<br />
These are extra tests like how to use fading effect, an fpGUI theme, games like maze and puzzle, how we created the material design animation, pix2svg or how to convert a small picture to svg using hexagons, rectangles and ellipses, plugins or how to load .dlls and use into a TBGRAVirtualScreen, rain effect, shadow effect, 9-slice-scaling with Custom Drawn or how to theme with bitmaps an application to look like Windows themes and 9-slice-scaling with charts.<br />
<br />
= Another units =<br />
<br />
These units come with BGRA Controls and contains more functionality that is sometimes used with the controls, sometimes not but are usefull in some way. Some are listed here, others you can see linked directly with any control like bcrtti, bcstylesform, bctools and bctypes.<br />
<br />
=== BCEffect ===<br />
<br />
Fading effect with BGRABitmap.<br />
<br />
=== BCFilters ===<br />
<br />
A set of pixel filters to use with BGRABitmap.<br />
<br />
=== BGRAScript ===<br />
<br />
Scripting with BGRABitmap, see test project.<br />
<br />
= Related Articles =<br />
<br />
[[BGRASpriteAnimation]] - Usage of the sprite animation component.<br />
<br />
[[uE_Controls]] - Other controls developed with BGRABitmap.<br />
<br />
[[BGRABitmap]] - The library used to create this controls.<br />
<br />
[[LazPaint]] - A paint program developed with Lazarus and BGRABitmap.<br />
<br />
[[Category:Components]]<br />
[[Category:Graphics]]<br />
[[Category:BGRAControls]]</div>007https://wiki.freepascal.org/index.php?title=File:bgracontrols.png&diff=130155File:bgracontrols.png2019-12-28T13:40:34Z<p>007: </p>
<hr />
<div></div>007https://wiki.freepascal.org/index.php?title=FileAssociation&diff=130032FileAssociation2019-12-23T21:13:19Z<p>007: /* Another way of registering file associations */</p>
<hr />
<div>{{FileAssociation}}<br />
<br />
{{Platform only|Windows}}<br />
<br />
== TFileAssociation ==<br />
<br />
Author: Lainz<br />
<br />
Licence: Modified LGPL<br />
<br />
Version: 1.0<br />
<br />
Description: This unit registers file association for Windows.<br />
<br />
== Download ==<br />
<br />
GitHub: https://github.com/lainz/FileAssociation<br />
<br />
== Usage ==<br />
<br />
First install the package. You can then drop the component TFileAssociation (FileAssoc unit) that gets installed in the [[System tab]] of the IDE on your [[TForm|form]].<br />
<br />
All parameters are mandatory. Especially ActionName which must be 'Open' to work with double click. This is useful as well for default commands like 'Edit' and 'Print'. This must be in English for 'Edit', 'Open' and 'Print' so it can access the right registry entry. You can customize the translation with ActionText.<br />
<br />
<syntaxhighlight lang="pascal"><br />
...<br />
uses<br />
...<br />
FileAssoc; //<-- add fileassociation unit here<br />
<br />
type<br />
<br />
...<br />
{ private declarations }<br />
assoc: TFileAssociation;<br />
...<br />
<br />
procedure TfrmMain.FormCreate(Sender: TObject);<br />
begin<br />
assoc := TFileAssociation.Create(Self);//<-- create like a regular component<br />
end;<br />
<br />
procedure TfrmMain.Button1Click(Sender: TObject);<br />
begin<br />
assoc.ApplicationName := 'Lazarus IDE';<br />
assoc.ApplicationDescription := 'RAD for Free Pascal';<br />
<br />
// you can change Extension and Action part for each extension you have<br />
<br />
assoc.Extension := '.lpr';<br />
assoc.ExtensionName := 'Lazarus Project';<br />
assoc.ExtensionIcon := '"C:\lazarus\images\lprfile.ico"';<br />
<br />
// full path required, you can use ParamStr(0) to get the path with the .exe name included. The path must be inside quotes if it has whitespace.<br />
assoc.Action := '"C:\lazarus\lazarus.exe" "%1"'; <br />
assoc.ActionName := 'Open';<br />
assoc.ActionIcon := '"C:\lazarus\images\mainicon.ico"';<br />
<br />
// notice that using RegisterForAllUsers as True requires Administrator Privileges<br />
// if you want to run without privileges set it to false, but it will register for current user only<br />
assoc.RegisterForAllUsers:=False;<br />
if assoc.Execute then<br />
begin<br />
ShowMessage('OK');<br />
assoc.ClearIconCache; //<<-- rebuild icons<br />
end;<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
== How to open the associated file ==<br />
<br />
<syntaxhighlight lang="pascal"><br />
procedure TForm1.FormCreate(Sender: TObject);<br />
var<br />
s: String;<br />
begin<br />
// if there are parameters<br />
if ParamCount > 0 then<br />
begin<br />
// load the first parameter<br />
s := ParamStr(1);<br />
<br />
// if is a .txt file<br />
if ExtractFileExt(s) = '.txt' then<br />
begin<br />
// load the .txt file into a memo<br />
Memo1.Lines.LoadFromFile(s);<br />
end;<br />
end;<br />
end; <br />
</syntaxhighlight><br />
<br />
== Another way of registering file associations ==<br />
<br />
Without using the component is as well possible to register a file association. This however doesn't cover adding the application to Default Programs, but is shorter if you only want to register a file type that's owned by your application.<br />
<br />
<syntaxhighlight lang="pascal"><br />
{$IFDEF WINDOWS}<br />
uses Registry, ShlObj;<br />
<br />
procedure TMainForm.RegisterFileType(ExtName: string; AppName: string);<br />
var<br />
reg: TRegistry;<br />
begin<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CLASSES_ROOT;<br />
reg.OpenKey('.' + ExtName, True);<br />
reg.WriteString('', ExtName + 'file');<br />
reg.CloseKey;<br />
reg.CreateKey(ExtName + 'file');<br />
reg.OpenKey(ExtName + 'file\DefaultIcon', True);<br />
reg.WriteString('', AppName + ',0');<br />
reg.CloseKey;<br />
reg.OpenKey(ExtName + 'file\shell\open\command', True);<br />
reg.WriteString('', AppName + ' "%1"');<br />
reg.CloseKey;<br />
finally<br />
reg.Free;<br />
end;<br />
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);<br />
end;<br />
{$ENDIF}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
var<br />
reg: TRegistry;<br />
<br />
begin<br />
{$IFDEF WINDOWS}<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CLASSES_ROOT;<br />
if not reg.KeyExists('ext' + 'file\shell\open\command') then<br />
RegisterFileType('ext', ExtractFilePath(Application.ExeName) + 'my_app.exe');<br />
finally<br />
reg.Free;<br />
end;<br />
<br />
if ParamCount > 0 then<br />
begin<br />
s := ParamStr(1);<br />
if ExtractFileExt(s) = '.ext' then<br />
LoadFile(s);<br />
end;<br />
{$ENDIF}<br />
</syntaxhighlight><br />
<br />
== See also ==<br />
<br />
If this component for some reason does not work for you, or you need to run it as administrator for all users without elevating your application privileges, an [[Inno_Setup_Usage#File_Association|Inno Setup Script]] may fit your needs best.</div>007https://wiki.freepascal.org/index.php?title=FileAssociation&diff=130024FileAssociation2019-12-23T19:58:50Z<p>007: /* Usage */</p>
<hr />
<div>{{FileAssociation}}<br />
<br />
{{Platform only|Windows}}<br />
<br />
== TFileAssociation ==<br />
<br />
Author: Lainz<br />
<br />
Licence: Modified LGPL<br />
<br />
Version: 1.0<br />
<br />
Description: This unit registers file association for Windows.<br />
<br />
== Download ==<br />
<br />
GitHub: https://github.com/lainz/FileAssociation<br />
<br />
== Usage ==<br />
<br />
First install the package. You can then drop the component TFileAssociation (FileAssoc unit) that gets installed in the [[System tab]] of the IDE on your [[TForm|form]].<br />
<br />
All parameters are mandatory. Specially ActionName, that must be 'Open' to work with double click. This is useful as well for default commands like 'Edit' and 'Print'. This must be in english for 'Edit', 'Open' and 'Print', so it can access the right registry entry. But you can customize the translation with ActionText.<br />
<br />
<syntaxhighlight lang="pascal"><br />
...<br />
uses<br />
...<br />
FileAssoc; //<-- add fileassociation unit here<br />
<br />
type<br />
<br />
...<br />
{ private declarations }<br />
assoc: TFileAssociation;<br />
...<br />
<br />
procedure TfrmMain.FormCreate(Sender: TObject);<br />
begin<br />
assoc := TFileAssociation.Create(Self);//<-- create like a regular component<br />
end;<br />
<br />
procedure TfrmMain.Button1Click(Sender: TObject);<br />
begin<br />
assoc.ApplicationName := 'Lazarus IDE';<br />
assoc.ApplicationDescription := 'RAD for Free Pascal';<br />
<br />
// you can change Extension and Action part for each extension you have<br />
<br />
assoc.Extension := '.lpr';<br />
assoc.ExtensionName := 'Lazarus Project';<br />
assoc.ExtensionIcon := '"C:\lazarus\images\lprfile.ico"';<br />
<br />
// full path required, you can use ParamStr(0) to get the path with the .exe name included. The path must be inside quotes if it has whitespace.<br />
assoc.Action := '"C:\lazarus\lazarus.exe" "%1"'; <br />
assoc.ActionName := 'Open';<br />
assoc.ActionIcon := '"C:\lazarus\images\mainicon.ico"';<br />
<br />
// notice that using RegisterForAllUsers as True requires Administrator Privileges<br />
// if you want to run without privileges set it to false, but it will register for current user only<br />
assoc.RegisterForAllUsers:=False;<br />
if assoc.Execute then<br />
begin<br />
ShowMessage('OK');<br />
assoc.ClearIconCache; //<<-- rebuild icons<br />
end;<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
== How to open the associated file ==<br />
<br />
<syntaxhighlight lang="pascal"><br />
procedure TForm1.FormCreate(Sender: TObject);<br />
var<br />
s: String;<br />
begin<br />
// if there are parameters<br />
if ParamCount > 0 then<br />
begin<br />
// load the first parameter<br />
s := ParamStr(1);<br />
<br />
// if is a .txt file<br />
if ExtractFileExt(s) = '.txt' then<br />
begin<br />
// load the .txt file into a memo<br />
Memo1.Lines.LoadFromFile(s);<br />
end;<br />
end;<br />
end; <br />
</syntaxhighlight><br />
<br />
== Another way of registering file associations ==<br />
<br />
Without using the component is as well possible to register a file association. This however doesn't cover adding the application to Default Programs, but is shorter if you only want to register a file type that's owned by your application.<br />
<br />
<syntaxhighlight lang="pascal"><br />
{$IFDEF WINDOWS}<br />
uses Registry, ShlObj;<br />
<br />
procedure TMainForm.RegisterFileType(ExtName: string; AppName: string);<br />
var<br />
reg: TRegistry;<br />
begin<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CLASSES_ROOT;<br />
reg.OpenKey('.' + ExtName, True);<br />
reg.WriteString('', ExtName + 'file');<br />
reg.CloseKey;<br />
reg.CreateKey(ExtName + 'file');<br />
reg.OpenKey(ExtName + 'file\DefaultIcon', True);<br />
reg.WriteString('', AppName + ',0');<br />
reg.CloseKey;<br />
reg.OpenKey(ExtName + 'file\shell\open\command', True);<br />
reg.WriteString('', AppName + ' "%1"');<br />
reg.CloseKey;<br />
finally<br />
reg.Free;<br />
end;<br />
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);<br />
end;<br />
{$ENDIF}<br />
</syntaxhighlight><br />
<br />
== See also ==<br />
<br />
If this component for some reason does not work for you, or you need to run it as administrator for all users without elevating your application privileges, an [[Inno_Setup_Usage#File_Association|Inno Setup Script]] may fit your needs best.</div>007https://wiki.freepascal.org/index.php?title=FileAssociation&diff=130015FileAssociation2019-12-23T15:38:11Z<p>007: /* Another way of registering file associations */</p>
<hr />
<div>{{FileAssociation}}<br />
<br />
{{Platform only|Windows}}<br />
<br />
== TFileAssociation ==<br />
<br />
Author: Lainz<br />
<br />
Licence: Modified LGPL<br />
<br />
Version: 1.0<br />
<br />
Description: This unit registers file association for Windows.<br />
<br />
== Download ==<br />
<br />
GitHub: https://github.com/lainz/FileAssociation<br />
<br />
== Usage ==<br />
<br />
First install the package. You can then drop the component TFileAssociation (FileAssoc unit) that gets installed in the [[System tab]] of the IDE on your [[TForm|form]].<br />
<br />
<syntaxhighlight lang="pascal"><br />
...<br />
uses<br />
...<br />
FileAssoc; //<-- add fileassociation unit here<br />
<br />
type<br />
<br />
...<br />
{ private declarations }<br />
assoc: TFileAssociation;<br />
...<br />
<br />
procedure TfrmMain.FormCreate(Sender: TObject);<br />
begin<br />
assoc := TFileAssociation.Create(Self);//<-- create like a regular component<br />
end;<br />
<br />
procedure TfrmMain.Button1Click(Sender: TObject);<br />
begin<br />
assoc.ApplicationName := 'Lazarus IDE';<br />
assoc.ApplicationDescription := 'RAD for Free Pascal';<br />
<br />
// you can change Extension and Action part for each extension you have<br />
<br />
assoc.Extension := '.lpr';<br />
assoc.ExtensionName := 'Lazarus Project';<br />
assoc.ExtensionIcon := '"C:\lazarus\images\lprfile.ico"';<br />
<br />
// full path required, you can use ParamStr(0) to get the path with the .exe name included. The path must be inside quotes if it has whitespace.<br />
assoc.Action := '"C:\lazarus\lazarus.exe" "%1"'; <br />
assoc.ActionName := 'Open';<br />
assoc.ActionIcon := '"C:\lazarus\images\mainicon.ico"';<br />
<br />
// notice that using RegisterForAllUsers as True requires Administrator Privileges<br />
// if you want to run without privileges set it to false, but it will register for current user only<br />
assoc.RegisterForAllUsers:=False;<br />
if assoc.Execute then<br />
begin<br />
ShowMessage('OK');<br />
assoc.ClearIconCache; //<<-- rebuild icons<br />
end;<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
== How to open the associated file ==<br />
<br />
<syntaxhighlight lang="pascal"><br />
procedure TForm1.FormCreate(Sender: TObject);<br />
var<br />
s: String;<br />
begin<br />
// if there are parameters<br />
if ParamCount > 0 then<br />
begin<br />
// load the first parameter<br />
s := ParamStr(1);<br />
<br />
// if is a .txt file<br />
if ExtractFileExt(s) = '.txt' then<br />
begin<br />
// load the .txt file into a memo<br />
Memo1.Lines.LoadFromFile(s);<br />
end;<br />
end;<br />
end; <br />
</syntaxhighlight><br />
<br />
== Another way of registering file associations ==<br />
<br />
Without using the component is as well possible to register a file association. This however doesn't cover adding the application to Default Programs, but is shorter if you only want to register a file type that's owned by your application.<br />
<br />
<syntaxhighlight lang="pascal"><br />
{$IFDEF WINDOWS}<br />
uses Registry, ShlObj;<br />
<br />
procedure TMainForm.RegisterFileType(ExtName: string; AppName: string);<br />
var<br />
reg: TRegistry;<br />
begin<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CLASSES_ROOT;<br />
reg.OpenKey('.' + ExtName, True);<br />
reg.WriteString('', ExtName + 'file');<br />
reg.CloseKey;<br />
reg.CreateKey(ExtName + 'file');<br />
reg.OpenKey(ExtName + 'file\DefaultIcon', True);<br />
reg.WriteString('', AppName + ',0');<br />
reg.CloseKey;<br />
reg.OpenKey(ExtName + 'file\shell\open\command', True);<br />
reg.WriteString('', AppName + ' "%1"');<br />
reg.CloseKey;<br />
finally<br />
reg.Free;<br />
end;<br />
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);<br />
end;<br />
{$ENDIF}<br />
</syntaxhighlight><br />
<br />
== See also ==<br />
<br />
If this component for some reason does not work for you, or you need to run it as administrator for all users without elevating your application privileges, an [[Inno_Setup_Usage#File_Association|Inno Setup Script]] may fit your needs best.</div>007https://wiki.freepascal.org/index.php?title=FileAssociation&diff=130014FileAssociation2019-12-23T15:37:40Z<p>007: </p>
<hr />
<div>{{FileAssociation}}<br />
<br />
{{Platform only|Windows}}<br />
<br />
== TFileAssociation ==<br />
<br />
Author: Lainz<br />
<br />
Licence: Modified LGPL<br />
<br />
Version: 1.0<br />
<br />
Description: This unit registers file association for Windows.<br />
<br />
== Download ==<br />
<br />
GitHub: https://github.com/lainz/FileAssociation<br />
<br />
== Usage ==<br />
<br />
First install the package. You can then drop the component TFileAssociation (FileAssoc unit) that gets installed in the [[System tab]] of the IDE on your [[TForm|form]].<br />
<br />
<syntaxhighlight lang="pascal"><br />
...<br />
uses<br />
...<br />
FileAssoc; //<-- add fileassociation unit here<br />
<br />
type<br />
<br />
...<br />
{ private declarations }<br />
assoc: TFileAssociation;<br />
...<br />
<br />
procedure TfrmMain.FormCreate(Sender: TObject);<br />
begin<br />
assoc := TFileAssociation.Create(Self);//<-- create like a regular component<br />
end;<br />
<br />
procedure TfrmMain.Button1Click(Sender: TObject);<br />
begin<br />
assoc.ApplicationName := 'Lazarus IDE';<br />
assoc.ApplicationDescription := 'RAD for Free Pascal';<br />
<br />
// you can change Extension and Action part for each extension you have<br />
<br />
assoc.Extension := '.lpr';<br />
assoc.ExtensionName := 'Lazarus Project';<br />
assoc.ExtensionIcon := '"C:\lazarus\images\lprfile.ico"';<br />
<br />
// full path required, you can use ParamStr(0) to get the path with the .exe name included. The path must be inside quotes if it has whitespace.<br />
assoc.Action := '"C:\lazarus\lazarus.exe" "%1"'; <br />
assoc.ActionName := 'Open';<br />
assoc.ActionIcon := '"C:\lazarus\images\mainicon.ico"';<br />
<br />
// notice that using RegisterForAllUsers as True requires Administrator Privileges<br />
// if you want to run without privileges set it to false, but it will register for current user only<br />
assoc.RegisterForAllUsers:=False;<br />
if assoc.Execute then<br />
begin<br />
ShowMessage('OK');<br />
assoc.ClearIconCache; //<<-- rebuild icons<br />
end;<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
== How to open the associated file ==<br />
<br />
<syntaxhighlight lang="pascal"><br />
procedure TForm1.FormCreate(Sender: TObject);<br />
var<br />
s: String;<br />
begin<br />
// if there are parameters<br />
if ParamCount > 0 then<br />
begin<br />
// load the first parameter<br />
s := ParamStr(1);<br />
<br />
// if is a .txt file<br />
if ExtractFileExt(s) = '.txt' then<br />
begin<br />
// load the .txt file into a memo<br />
Memo1.Lines.LoadFromFile(s);<br />
end;<br />
end;<br />
end; <br />
</syntaxhighlight><br />
<br />
== Another way of registering file associations ==<br />
<br />
Whithout using the component is as well possible to register a file association. This however doesn't cover adding the application to Default Programs, but is shorter if you only want to register a file type that's owned by your application.<br />
<br />
<syntaxhighlight lang="pascal"><br />
{$IFDEF WINDOWS}<br />
uses Registry, ShlObj;<br />
<br />
procedure TMainForm.RegisterFileType(ExtName: string; AppName: string);<br />
var<br />
reg: TRegistry;<br />
begin<br />
reg := TRegistry.Create;<br />
try<br />
reg.RootKey := HKEY_CLASSES_ROOT;<br />
reg.OpenKey('.' + ExtName, True);<br />
reg.WriteString('', ExtName + 'file');<br />
reg.CloseKey;<br />
reg.CreateKey(ExtName + 'file');<br />
reg.OpenKey(ExtName + 'file\DefaultIcon', True);<br />
reg.WriteString('', AppName + ',0');<br />
reg.CloseKey;<br />
reg.OpenKey(ExtName + 'file\shell\open\command', True);<br />
reg.WriteString('', AppName + ' "%1"');<br />
reg.CloseKey;<br />
finally<br />
reg.Free;<br />
end;<br />
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);<br />
end;<br />
{$ENDIF}<br />
</syntaxhighlight><br />
<br />
== See also ==<br />
<br />
If this component for some reason does not work for you, or you need to run it as administrator for all users without elevating your application privileges, an [[Inno_Setup_Usage#File_Association|Inno Setup Script]] may fit your needs best.</div>007https://wiki.freepascal.org/index.php?title=Inno_Setup_Usage&diff=129939Inno Setup Usage2019-12-22T14:59:33Z<p>007: /* File Association */</p>
<hr />
<div>{{Platform only|Windows|Windows|Windows}}<br />
Inno Setup ([http://www.jrsoftware.org/isinfo.php home]) is a program that lets you create Windows installers for your programs. It is coded in Delphi and has Unicode support. It is one of the most often used programs to create setup files (alongside with nsis). The advantage of Inno Setup is that it supports Pascal Scripting for more advanced tasks (although the built in capabilities are already very extensive).<br />
<br />
Like nsis, Inno Setup uses script files (.iss) to indicate what files to install and where. While you can create these with a simple text editor, there are some IDEs for Inno Setup that provide easier editing.<br />
<br />
Inno Setup comes with extensive help on the syntax of the script file.<br />
<br />
== Features ==<br />
Features:<br />
* Inno supports all versions of Windows in use today -- Windows 95, 98, ME, NT4, 2000, 2003, XP, Vista, 7, 8 and 10. The latest version that can create installers for Windows versions before Windows 2000 is version 5.4. See [http://www.jrsoftware.org/files/is5-whatsnew.htm]<br />
* It can compare file version info, replace in-use files, use shared file counting.<br />
* It can register DLL/OCXs and type libraries<br />
* It can install fonts.<br />
* It can create shortcuts anywhere, including in the Start Menu and on the desktop. <br />
* It can create registry and .INI entries<br />
* It has integrated Pascal scripting engine that allows e.g. manipulation of COM/ActiveX objects (e.g. MS Word), setting firewall rules etc.<br />
* It supports multilingual installs<br />
* It supports passworded and encrypted installs<br />
* It supports silent install and uninstall.<br />
<br />
== Inno Setup for Linux/OSX? ==<br />
Occassionally, on forums and mailing lists, people ask why there is no Inno Setup for OSX or Linux. However, many people agree that you should use the distribution package manager format (e.g. .rpm, .deb) for Linux and the standard OSX way (e.g. .dmg disk images with the Apple-provided tools) for that; see [[Deploying_Your_Application#Unix_installers|this article for details]].<br />
See e.g. [http://www.lazarus.freepascal.org/index.php/topic,14789.msg78576.html this forum discussion] for an example.<br />
<br />
== Download ==<br />
[http://www.jrsoftware.org/isdl.php#qsp Download Inno Setup Quick Start Pack] is the recommended download. It contains Inno Setup, some IDEs and a preprocessor.<br />
<br />
== Examples ==<br />
* The Lazarus setup for Windows was created with Inno Setup. This script includes PascalScript sections used to customize the installer, which may serve as inspiration for your own installers.<br />
<br />
* [[LazPaint]] setup was also created with it.<br />
<br />
Both scripts have File Association support and are listed in Default Programs to restore the file associations if needed (Windows 7).<br />
<br />
Below we show some example of Inno Setup usage. Please have a look at their extensive help files and web site for information on how to perform other tasks.<br />
<br />
=== Full example ===<br />
<br />
This example is full of things: Translations, File Associations, Default Programs, Right-click with Cascade-Menu, Add to Open With list, Add to 'App Paths' (to execute application from Windows+R 'Run' window, from batch files or by code just typing the executable name (lazpaint.exe in this case).<br />
<br />
<syntaxhighlight lang="reg"><br />
#define MyAppName "LazPaint"<br />
#define MyAppOutputName "lazpaint"<br />
#define MyInstallerSuffix "_setup_win32_win64"<br />
#define MyAppVersion "6.4.1"<br />
#define MyAppPublisher "Circular, Fabien Wang, Lainz and others"<br />
#define MyAppURL "http://sourceforge.net/projects/lazpaint/"<br />
#define MyAppExeName "lazpaint.exe"<br />
#define ReleaseDir "release\"<br />
#define BasicSubCommands "LazPaint.horizontalflip;LazPaint.verticalflip;Windows.separator;LazPaint.rotatecw;LazPaint.rotateccw;Windows.separator;LazPaint.swapredblue"<br />
#define EffectsSubCommands "LazPaint.sharpen;LazPaint.smooth;LazPaint.median;LazPaint.cleartype;LazPaint.cleartypeinverse;LazPaint.emboss;LazPaint.contour;LazPaint.grayscale;LazPaint.negative;LazPaint.linearnegative;LazPaint.complementarycolor;LazPaint.normalize;LazPaint.smartzoom3"<br />
<br />
[Setup]<br />
AppId={{A177F82E-B44A-4348-A265-3D1C089D6304}<br />
AppName={#MyAppName}<br />
AppVersion={#MyAppVersion}<br />
AppPublisher={#MyAppPublisher}<br />
AppPublisherURL={#MyAppURL}<br />
AppSupportURL={#MyAppURL}<br />
AppUpdatesURL={#MyAppURL}<br />
ChangesAssociations=yes<br />
DefaultDirName={pf}\{#MyAppName}<br />
DefaultGroupName={#MyAppName}<br />
AllowNoIcons=yes<br />
OutputDir=installer<br />
OutputBaseFilename={#MyAppOutputName}{#MyAppVersion}{#MyInstallerSuffix}<br />
Compression=lzma2/ultra64<br />
InternalCompressLevel=ultra<br />
SolidCompression=yes<br />
CompressionThreads=2<br />
ArchitecturesInstallIn64BitMode=x64<br />
WizardImageFile=lazpaint_setup.bmp<br />
WizardSmallImageFile=lazpaint_setup_icon.bmp<br />
WizardImageBackColor=clWhite<br />
WizardImageStretch=False<br />
;The next options are to do a quick setup with less dialogs<br />
;If program already installed only show tasks dialog<br />
;ShowLanguageDialog=no<br />
;DisableWelcomePage=yes<br />
;DisableDirPage=auto<br />
;DisableProgramGroupPage=auto<br />
;DisableReadyPage=yes<br />
;DisableFinishedPage=yes<br />
<br />
[Code]<br />
// Start - Quick Setup //<br />
{procedure CurPageChanged(CurPageID: Integer);<br />
begin<br />
if CurPageID = wpSelectTasks then<br />
WizardForm.NextButton.Caption := SetupMessage(msgButtonInstall)<br />
else if CurPageID = wpFinished then<br />
WizardForm.NextButton.Caption := SetupMessage(msgButtonFinish)<br />
else<br />
WizardForm.NextButton.Caption := SetupMessage(msgButtonNext);<br />
end;}<br />
// End - Quick Setup //<br />
<br />
[Languages]<br />
Name: "english"; MessagesFile: "compiler:Default.isl"<br />
Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"<br />
Name: "catalan"; MessagesFile: "compiler:Languages\Catalan.isl"<br />
Name: "corsican"; MessagesFile: "compiler:Languages\Corsican.isl"<br />
Name: "czech"; MessagesFile: "compiler:Languages\Czech.isl"<br />
Name: "danish"; MessagesFile: "compiler:Languages\Danish.isl"<br />
Name: "dutch"; MessagesFile: "compiler:Languages\Dutch.isl"<br />
Name: "finnish"; MessagesFile: "compiler:Languages\Finnish.isl"<br />
Name: "french"; MessagesFile: "compiler:Languages\French.isl"<br />
Name: "german"; MessagesFile: "compiler:Languages\German.isl"<br />
Name: "greek"; MessagesFile: "compiler:Languages\Greek.isl"<br />
Name: "hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl"<br />
Name: "hungarian"; MessagesFile: "compiler:Languages\Hungarian.isl"<br />
Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"<br />
Name: "japanese"; MessagesFile: "compiler:Languages\Japanese.isl"<br />
Name: "norwegian"; MessagesFile: "compiler:Languages\Norwegian.isl"<br />
Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl"<br />
Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl"<br />
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"<br />
Name: "serbiancyrillic"; MessagesFile: "compiler:Languages\SerbianCyrillic.isl"<br />
Name: "serbianlatin"; MessagesFile: "compiler:Languages\SerbianLatin.isl"<br />
Name: "slovenian"; MessagesFile: "compiler:Languages\Slovenian.isl"<br />
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"<br />
Name: "ukrainian"; MessagesFile: "compiler:Languages\Ukrainian.isl"<br />
<br />
[CustomMessages]<br />
; English<br />
english.LazPaintDescription=This program is designed to draw like with Paint.Net and to experiment this kind of programming with Lazarus.<br />
; English.AssocFile<br />
english.AssocFileLZP=LazPaint image<br />
english.AssocFileORA=OpenRaster format<br />
english.AssocFileBMP=Bitmap<br />
english.AssocFilePNG=Portable Network Graphic<br />
english.AssocFileJPG=JPEG<br />
english.AssocFilePDN=Paint.NET image<br />
english.AssocFileGIF=Animated GIF<br />
english.AssocFileICO=Icon<br />
english.AssocFilePCX=Personal Computer eXchange<br />
; English.Menu<br />
english.QuickEdit=Quick Edit<br />
english.QuickEffects=Quick Effects<br />
; English.QuickEdit<br />
english.Open=Open<br />
english.HorizontalFlip=Horizontal Flip<br />
english.VerticalFlip=Vertical Flip<br />
english.SwapRedBlue=Swap Red and Blue Channels<br />
english.RotateCW=Rotate Clock Wise<br />
english.RotateCCW=Rotate Counter Clock Wise<br />
; English.QuickEffects<br />
english.Sharpen=Sharpen<br />
english.Smooth=Smooth<br />
english.Median=Median<br />
english.ClearType=Clear Type<br />
english.ClearTypeInverse=Clear Type Inverse<br />
english.Emboss=Emboss<br />
english.Contour=Contour<br />
english.Grayscale=Grayscale<br />
english.Negative=Negative<br />
english.LinearNegative=Linear Negative<br />
english.ComplementaryColor=Complementary Color<br />
english.Normalize=Normalize<br />
english.SmartZoom3=SmartZoom3<br />
<br />
; Spanish<br />
spanish.LazPaintDescription=Este programa esta diseñado para dibujar como Paint.Net y para experimentar este tipo de programación con Lazarus.<br />
; Spanish.AssocFile<br />
spanish.AssocFileLZP=Imágen LazPaint<br />
spanish.AssocFileORA=Formato OpenRaster<br />
spanish.AssocFileBMP=Mapa de Bits<br />
spanish.AssocFilePNG=Portable Network Graphic<br />
spanish.AssocFileJPG=JPEG<br />
spanish.AssocFilePDN=Imágen Paint.NET<br />
spanish.AssocFileGIF=GIF Animado<br />
spanish.AssocFileICO=Icono<br />
spanish.AssocFilePCX=Personal Computer eXchange<br />
; Spanish.Menu<br />
spanish.QuickEdit=Edición Rápida<br />
spanish.QuickEffects=Efectos Rápidos<br />
; Spanish.QuickEdit<br />
spanish.Open=Abrir<br />
spanish.HorizontalFlip=Voltear Horizontalmente<br />
spanish.VerticalFlip=Voltear Verticalmente<br />
spanish.SwapRedBlue=Intercambiar Canales Rojo y Azul<br />
spanish.RotateCW=Rotar en Sentido Horario<br />
spanish.RotateCCW=Rotar en Sentido Antihorario<br />
; Spanish.QuickEffects<br />
spanish.Sharpen=Sharpen<br />
spanish.Smooth=Smooth<br />
spanish.Median=Median<br />
spanish.ClearType=Clear Type<br />
spanish.ClearTypeInverse=Clear Type Inverse<br />
spanish.Emboss=Emboss<br />
spanish.Contour=Contour<br />
spanish.Grayscale=Grayscale<br />
spanish.Negative=Negative<br />
spanish.LinearNegative=Linear Negative<br />
spanish.ComplementaryColor=Complementary Color<br />
spanish.Normalize=Normalize<br />
spanish.SmartZoom3=SmartZoom3<br />
<br />
[Tasks]<br />
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"<br />
Name: "assoc_lzp"; Description: "{cm:AssocFileExtension,{#MyAppName},.lzp}"<br />
Name: "assoc_ora"; Description: "{cm:AssocFileExtension,{#MyAppName},.ora}"<br />
Name: "assoc_pdn"; Description: "{cm:AssocFileExtension,{#MyAppName},.pdn}"; Flags: unchecked<br />
Name: "assoc_bmp"; Description: "{cm:AssocFileExtension,{#MyAppName},.bmp}"; Flags: unchecked<br />
Name: "assoc_pcx"; Description: "{cm:AssocFileExtension,{#MyAppName},.pcx}"; Flags: unchecked<br />
Name: "assoc_png"; Description: "{cm:AssocFileExtension,{#MyAppName},.png}"; Flags: unchecked<br />
Name: "assoc_jpg"; Description: "{cm:AssocFileExtension,{#MyAppName},.jpg}"; Flags: unchecked<br />
Name: "assoc_gif"; Description: "{cm:AssocFileExtension,{#MyAppName},.gif}"; Flags: unchecked<br />
Name: "assoc_ico"; Description: "{cm:AssocFileExtension,{#MyAppName},.ico}"; Flags: unchecked<br />
<br />
[Files]<br />
Source: "{#ReleaseDir}lazpaint32.exe"; DestDir: "{app}"; DestName: "{#MyAppExeName}"; Flags: ignoreversion; Check: not Is64BitInstallMode<br />
Source: "{#ReleaseDir}lazpaint_x64.exe"; DestDir: "{app}"; DestName: "{#MyAppExeName}"; Flags: ignoreversion; Check: Is64BitInstallMode<br />
Source: "{#ReleaseDir}i18n\*.po"; DestDir: "{app}\i18n"; Excludes: "i18n\lazpaint_x64.po"; Flags: ignoreversion<br />
Source: "{#ReleaseDir}models\*.*"; DestDir: "{app}\models"; Flags: ignoreversion<br />
Source: "{#ReleaseDir}readme.txt"; DestDir: "{app}"; Flags: ignoreversion<br />
<br />
[Icons]<br />
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Comment: "LazPaint"<br />
Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"<br />
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"<br />
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Comment: "LazPaint"; Tasks: desktopicon<br />
<br />
[Run]<br />
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, "&", "&&")}}"; Flags: nowait postinstall skipifsilent<br />
<br />
[Registry]<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp"; ValueType: String; ValueData: "{cm:AssocFileLZP}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp\Shell\CascadeMenu\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEdit}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp\Shell\CascadeMenu\"; ValueType: String; ValueName: SubCommands; ValueData: "{#BasicSubCommands}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp\Shell\CascadeMenu2\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEffects}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp\Shell\CascadeMenu2\"; ValueType: String; ValueName: SubCommands; ValueData: "{#EffectsSubCommands}"; Flags: uninsdeletekey<br />
; Windows XP compatibility<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp\Shell\CascadeMenu\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.lzp\Shell\CascadeMenu2\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora"; ValueType: String; ValueData: "{cm:AssocFileORA}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora\Shell\CascadeMenu\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEdit}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora\Shell\CascadeMenu\"; ValueType: String; ValueName: SubCommands; ValueData: "{#BasicSubCommands}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora\Shell\CascadeMenu2\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEffects}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora\Shell\CascadeMenu2\"; ValueType: String; ValueName: SubCommands; ValueData: "{#EffectsSubCommands}"; Flags: uninsdeletekey<br />
; Windows XP compatibility<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora\Shell\CascadeMenu\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ora\Shell\CascadeMenu2\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp"; ValueType: String; ValueData: "{cm:AssocFileBMP}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\CascadeMenu\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEdit}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\CascadeMenu\"; ValueType: String; ValueName: SubCommands; ValueData: "{#BasicSubCommands}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\CascadeMenu2\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEffects}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\CascadeMenu2\"; ValueType: String; ValueName: SubCommands; ValueData: "{#EffectsSubCommands}"; Flags: uninsdeletekey<br />
; Windows XP compatibility<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\CascadeMenu\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\CascadeMenu2\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png"; ValueType: String; ValueData: "{cm:AssocFilePNG}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png\Shell\CascadeMenu\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEdit}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png\Shell\CascadeMenu\"; ValueType: String; ValueName: SubCommands; ValueData: "{#BasicSubCommands}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png\Shell\CascadeMenu2\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEffects}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png\Shell\CascadeMenu2\"; ValueType: String; ValueName: SubCommands; ValueData: "{#EffectsSubCommands}"; Flags: uninsdeletekey<br />
; Windows XP compatibility<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png\Shell\CascadeMenu\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.png\Shell\CascadeMenu2\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg"; ValueType: String; ValueData: "{cm:AssocFileJPG}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg\Shell\CascadeMenu\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEdit}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg\Shell\CascadeMenu\"; ValueType: String; ValueName: SubCommands; ValueData: "{#BasicSubCommands}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg\Shell\CascadeMenu2\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEffects}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg\Shell\CascadeMenu2\"; ValueType: String; ValueName: SubCommands; ValueData: "{#EffectsSubCommands}"; Flags: uninsdeletekey<br />
; Windows XP compatibility<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg\Shell\CascadeMenu\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.jpg\Shell\CascadeMenu2\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn"; ValueType: String; ValueData: "{cm:AssocFilePDN}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn\Shell\CascadeMenu\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEdit}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn\Shell\CascadeMenu\"; ValueType: String; ValueName: SubCommands; ValueData: "{#BasicSubCommands}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn\Shell\CascadeMenu2\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEffects}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn\Shell\CascadeMenu2\"; ValueType: String; ValueName: SubCommands; ValueData: "{#EffectsSubCommands}"; Flags: uninsdeletekey<br />
; Windows XP compatibility<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn\Shell\CascadeMenu\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pdn\Shell\CascadeMenu2\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif"; ValueType: String; ValueData: "{cm:AssocFileGIF}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif\Shell\CascadeMenu\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEdit}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif\Shell\CascadeMenu\"; ValueType: String; ValueName: SubCommands; ValueData: "{#BasicSubCommands}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif\Shell\CascadeMenu2\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEffects}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif\Shell\CascadeMenu2\"; ValueType: String; ValueName: SubCommands; ValueData: "{#EffectsSubCommands}"; Flags: uninsdeletekey<br />
; Windows XP compatibility<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif\Shell\CascadeMenu\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.gif\Shell\CascadeMenu2\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico"; ValueType: String; ValueData: "{cm:AssocFileICO}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico\Shell\CascadeMenu\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEdit}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico\Shell\CascadeMenu\"; ValueType: String; ValueName: SubCommands; ValueData: {#BasicSubCommands}; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico\Shell\CascadeMenu2\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEffects}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico\Shell\CascadeMenu2\"; ValueType: String; ValueName: SubCommands; ValueData: "{#EffectsSubCommands}"; Flags: uninsdeletekey<br />
; Windows XP compatibility<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico\Shell\CascadeMenu\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.ico\Shell\CascadeMenu2\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx"; ValueType: String; ValueData: "{cm:AssocFilePCX}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx\Shell\CascadeMenu\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEdit}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx\Shell\CascadeMenu\"; ValueType: String; ValueName: SubCommands; ValueData: {#BasicSubCommands}; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx\Shell\CascadeMenu2\"; ValueType: String; ValueName: MUIVerb; ValueData: "{cm:QuickEffects}"; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx\Shell\CascadeMenu2\"; ValueType: String; ValueName: SubCommands; ValueData: "{#EffectsSubCommands}"; Flags: uninsdeletekey<br />
; Windows XP compatibility<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx\Shell\CascadeMenu\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.pcx\Shell\CascadeMenu2\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
; BasicSubCommands methods<br />
; Open<br />
;Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.open"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:Open}; Flags: uninsdeletekey<br />
;Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.open\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
; HorizontalFlip<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.horizontalflip"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:HorizontalFlip}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.horizontalflip\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/HorizontalFlip"" ""%1"""; Flags: uninsdeletekey<br />
; VerticalFlip<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.verticalflip"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:VerticalFlip}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.verticalflip\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/VerticalFlip"" ""%1"""; Flags: uninsdeletekey<br />
; SwapRedBlue<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.swapredblue"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:SwapRedBlue}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.swapredblue\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/SwapRedBlue"" ""%1"""; Flags: uninsdeletekey<br />
; RotateCW<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.rotatecw"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:RotateCW}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.rotatecw\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/RotateCW"" ""%1"""; Flags: uninsdeletekey<br />
; RotateCCW<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.rotateccw"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:RotateCCW}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.rotateccw\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/RotateCCW"" ""%1"""; Flags: uninsdeletekey<br />
<br />
; EffectsSubCommands methods<br />
; Sharpen<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.sharpen"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:Sharpen}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.sharpen\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/Sharpen"" ""%1"""; Flags: uninsdeletekey<br />
; Smooth<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.smooth"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:Smooth}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.smooth\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/Smooth"" ""%1"""; Flags: uninsdeletekey<br />
; Median<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.median"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:Median}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.median\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/Median"" ""%1"""; Flags: uninsdeletekey<br />
; ClearType<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.cleartype"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:ClearType}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.cleartype\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/ClearType"" ""%1"""; Flags: uninsdeletekey<br />
; ClearTypeInverse<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.cleartypeinverse"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:ClearTypeInverse}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.cleartypeinverse\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/ClearTypeInverse"" ""%1"""; Flags: uninsdeletekey<br />
; Emboss<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.emboss"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:Emboss}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.emboss\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/Emboss"" ""%1"""; Flags: uninsdeletekey<br />
; Contour<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.contour"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:Contour}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.contour\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/Contour"" ""%1"""; Flags: uninsdeletekey<br />
; Grayscale<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.grayscale"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:Grayscale}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.grayscale\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/Grayscale"" ""%1"""; Flags: uninsdeletekey<br />
; Negative<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.negative"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:Negative}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.negative\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/Negative"" ""%1"""; Flags: uninsdeletekey<br />
; LinearNegative<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.linearnegative"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:LinearNegative}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.linearnegative\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/LinearNegative"" ""%1"""; Flags: uninsdeletekey<br />
; ComplementaryColor<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.complementarycolor"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:ComplementaryColor}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.complementarycolor\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/ComplementaryColor"" ""%1"""; Flags: uninsdeletekey<br />
; Normalize<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.normalize"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:Normalize}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.normalize\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/Normalize"" ""%1"""; Flags: uninsdeletekey<br />
; SmartZoom3<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.smartzoom3"; ValueName: MUIVerb; ValueType: String; ValueData: {cm:SmartZoom3}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\LazPaint.smartzoom3\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"" ""/SmartZoom3"" ""%1"""; Flags: uninsdeletekey<br />
<br />
; Real file association<br />
Root: HKLM; Subkey: "Software\Classes\.bmp"; ValueType: String; ValueData: "LazPaint.AssocFile.bmp"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_bmp<br />
Root: HKLM; Subkey: "Software\Classes\.lzp"; ValueType: String; ValueData: "LazPaint.AssocFile.lzp"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_lzp<br />
Root: HKLM; Subkey: "Software\Classes\.ora"; ValueType: String; ValueData: "LazPaint.AssocFile.ora"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_ora<br />
Root: HKLM; Subkey: "Software\Classes\.png"; ValueType: String; ValueData: "LazPaint.AssocFile.png"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_png<br />
Root: HKLM; Subkey: "Software\Classes\.jpg"; ValueType: String; ValueData: "LazPaint.AssocFile.jpg"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_jpg<br />
Root: HKLM; Subkey: "Software\Classes\.pdn"; ValueType: String; ValueData: "LazPaint.AssocFile.pdn"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_pdn<br />
Root: HKLM; Subkey: "Software\Classes\.gif"; ValueType: String; ValueData: "LazPaint.AssocFile.gif"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_gif<br />
Root: HKLM; Subkey: "Software\Classes\.ico"; ValueType: String; ValueData: "LazPaint.AssocFile.ico"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_ico<br />
Root: HKLM; Subkey: "Software\Classes\.pcx"; ValueType: String; ValueData: "LazPaint.AssocFile.pcx"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_pcx<br />
<br />
; Control panel<br />
Root: HKLM; Subkey: "Software\LazPaint"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities"; ValueType: String; ValueName: "ApplicationName"; ValueData: "LazPaint"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities"; ValueType: String; ValueName: "ApplicationDescription"; ValueData: {cm:LazPaintDescription}; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".lzp"; ValueType: String; ValueData: "LazPaint.AssocFile.lzp"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".ora"; ValueType: String; ValueData: "LazPaint.AssocFile.ora"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".bmp"; ValueType: String; ValueData: "LazPaint.AssocFile.bmp"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".png"; ValueType: String; ValueData: "LazPaint.AssocFile.png"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".jpg"; ValueType: String; ValueData: "LazPaint.AssocFile.jpg"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".pdn"; ValueType: String; ValueData: "LazPaint.AssocFile.pdn"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".gif"; ValueType: String; ValueData: "LazPaint.AssocFile.gif"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".ico"; ValueType: String; ValueData: "LazPaint.AssocFile.ico"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".pcx"; ValueType: String; ValueData: "LazPaint.AssocFile.pcx"; Flags: uninsdeletekey<br />
<br />
Root: HKLM; Subkey: "Software\RegisteredApplications"; ValueType: String; ValueName: "LazPaint"; ValueData: "Software\LazPaint\Capabilities"; Flags: uninsdeletevalue uninsdeletekeyifempty<br />
<br />
; Open With...<br />
Root: HKLM; Subkey: "Software\Classes\Applications\lazpaint.exe\shell\open\command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey<br />
<br />
; App Paths (ShellExecuteEx)<br />
Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\lazpaint.exe"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"""; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\lazpaint.exe"; ValueType: String; ValueName: Path; ValueData: """{app}"""; Flags: uninsdeletekey</syntaxhighlight><br />
<br />
== File Association ==<br />
<br />
The file association code is in the [Registry] section of the script.<br />
<br />
The first thing we need is each type of association. In the example below, the type is for .bmp files. You can see the first line is for the description of the association 'Bitmap'. The second line is the icon for .bmp files in the explorer, the third is the icon for the right clic menu on .bmp files in the explorer, the last is the parameter to open the file.<br />
<br />
<syntaxhighlight lang="reg">[Registry]<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp"; ValueType: String; ValueData: "Bitmap"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\DefaultIcon"; ValueType: String; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\Open"; ValueName: Icon; ValueType: String; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\Classes\LazPaint.AssocFile.bmp\Shell\Open\Command"; ValueType: String; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey</syntaxhighlight><br />
<br />
That code doesn't associate anything, the following code is to associate our type 'LazPaint.AssocFile.bmp' with '.bmp'. It is only executed when the task assoc_bmp is selected. Read about tasks in the Inno Setup help.<br />
<br />
<syntaxhighlight lang="reg">Root: HKLM; Subkey: "Software\Classes\.bmp"; ValueType: String; ValueData: "LazPaint.AssocFile.bmp"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: assoc_bmp</syntaxhighlight><br />
<br />
That's all. Now we have associated .bmp with our program (LazPaint in the example).<br />
<br />
If you want to setup file associations from your program instead of a setup program use [[FileAssociation]] component instead.<br />
<br />
== Default Programs ==<br />
<br />
Default Programs is used to list the applications that have file association support. Values are the name of the app, a short description and each one of the extensions the program has support.<br />
<br />
<syntaxhighlight lang="reg">Root: HKLM; Subkey: "Software\LazPaint"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities"; ValueType: String; ValueName: "ApplicationName"; ValueData: "LazPaint"; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities"; ValueType: String; ValueName: "ApplicationDescription"; ValueData: "A short description..."; Flags: uninsdeletekey<br />
Root: HKLM; Subkey: "Software\LazPaint\Capabilities\FileAssociations"; ValueName: ".bmp"; ValueType: String; ValueData: "LazPaint.AssocFile.bmp"; Flags: uninsdeletekey</syntaxhighlight><br />
<br />
Finally we need to add the program to the 'Registered Applications':<br />
<br />
<syntaxhighlight>Root: HKLM; Subkey: "Software\RegisteredApplications"; ValueType: String; ValueName: "LazPaint"; ValueData: "Software\LazPaint\Capabilities"; Flags: uninsdeletevalue uninsdeletekeyifempty</syntaxhighlight><br />
<br />
[[Category:Tutorials]]<br />
[[Category:Windows]]<br />
[[Category: Pascal Script]]<br />
[[Category:PascalScript]]<br />
[[Category:Deployment]]</div>007https://wiki.freepascal.org/index.php?title=Windows_Programming_Tips&diff=129938Windows Programming Tips2019-12-22T14:26:44Z<p>007: /* File Association */</p>
<hr />
<div>{{Windows_Programming_Tips}}<br />
<br />
{{Platform only|Windows|Windows|Windows}}<br />
This page is dedicated to desktop Windows - including server - '''Windows programming tips'''.<br />
<br />
__TOC__<br />
<br />
{{Other Interfaces}}<br />
<br />
==Articles about Windows Programming==<br />
*[[High DPI]] - How to make your application DPI-aware on Windows 7.<br />
*[[Aero Glass]] - How to apply Aero Glass effect in a Lazarus Form on Windows 7.<br />
*[[Windows Icon]] - How to design your icon with the right sizes.<br />
*[[Inno Setup Usage]] - How to create setup files with File Association support.<br />
<br />
== FPC 2.6.x/Lazarus warning (Missing support for SEH) ==<br />
<div id="FPC_2.6.x.2FLazarus_warning"></div><br />
{{Warning|If you can avoid it, do not use Win64 builds of Lazarus based on FPC 2.6.x and earlier (this includes Lazarus 1.x). See below for details.}} <br />
<br />
Please be aware that all current Lazarus 1.x releases use FPC 2.6.x. FPC 2.6.x (and probably earlier versions as well) does not properly support Windows 64 bit. Therefore, please use the 32 bit Lazarus IDE on Win64. If it is absolutely necessary to build 64 bit executables (e.g. explorer extensions), please install the 64 bit cross compiler add on for the 32 bit IDE.<br />
<br />
Details of the bug: on Windows 64, exceptions in (third party) DLLs may be raised using SEH. These exceptions should be handled within the DLL itself.<br />
<br />
However, FPC sees an (incorrect) FPC exception which may cause your programs (or Lazarus) to crash.<br />
This applies to DLLs like printer drivers, database drivers, Windows explorer extensions.<br />
<br />
The issue has been fixed in the FPC development version but it is a major change and it will not be backported to FPC 2.6.x.<br />
<br />
Relevant bug reports include http://bugs.freepascal.org/view.php?id=12742<br />
<br />
==Windows specific compiler options==<br />
The most prominent options are the '''-W''' flags. A GUI application requires the '''-WG''' flag. See ''Project Options / Compiler Options / Linking / Target OS Specific options / Win32 GUI application''. No console is shown, '''writeln''' and '''readln''' are not possible, you will get '''File not open''' errors. Omitting this option creates a console application (same as passing -WC).<br />
<br />
==Writing cross-platform code that works on Windows==<br />
While you can use Windows-only code (such as the '''windows''' unit), with a little care you can often prepare for cross-platform use (e.g. use the [[lclintf]] unit).<br />
<br />
See [[Multiplatform Programming Guide#Windows specific issues|Windows specific issues]] for more details.<br />
<br />
==COM Programming==<br />
<br />
===Importing and using a COM library===<br />
The first step to import and use a COM library is generating the interface definitions from it. Use the program importtl which is located in Free Pascal in fpc/utils/importtl. A pre-compiled binary of this program can be found here: http://sourceforge.net/projects/p-tools/files/ImportTL/<br />
<br />
You can call it, for example for MSAA like this:<br />
<br />
importtl.exe C:\Windows\system32\oleacc.dll<br />
<br />
And it will generate the type library pascal unit Accessibility_1_1_TLB.pas in the folder where it is.<br />
<br />
===Creating a library which exports a COM object===<br />
<br />
ToDo: write me<br />
<br />
===Windows Sensor/Location API===<br />
Available since Windows 7. See [[LazDeviceAPIs#Possible Windows implementation|possible Windows implementation]]<br />
<br />
==ActiveX controls==<br />
You can use ActiveX controls in recent Lazarus versions. See [[LazActiveX]]<br />
<br />
==Services==<br />
Lazarus and FPC make writing Windows services easy. See [[Daemons and Services]]<br />
<br />
==Using sleep(n) and Application.ProcessMessages==<br />
<br />
Windows has a messaging system (see https://docs.microsoft.com/en-us/windows/desktop/winmsg/messages-and-message-queues) and uses messages to "talk" to all running applications. You obstruct that when using sleep(n). In such a case use Application.ProcessMessages instead of sleep(n) which is blocking. You have to give the OS the time to process its message queue. Application.ProcessMessages handles all waiting system messages in an application's message queue.<br />
<br />
There is one exception: sleep(0). This has a special meaning and means relinquish time slice. Any other sleep is almost always bad programming. <br />
<br />
Note that Application.ProcessMessages is called by the LCL automatically after every message (eg after every event like OnClick). So you would only need to call it in your event handler where there is a significant delay doing some processing. Of course, event handlers should probably not be doing any significant processing. Instead, you should be calling another function or procedure which may require the use of Application.ProcessMessages to ensure the application continues to respond to events and does not appear to have locked up. However, even in that case, it might be better to simply alert the user to the extended processing time (eg when compressing a file) by using the appropriate "busy" cursor or a progress bar.<br />
<br />
Beware of unintended consequences... sprinkling Application.ProcessMessages through your code like fairy dust may sound like a good idea, but consider what happens if your application is still busy with the task and an impatient user clicks that button a second time. That second click will be put into the Windows message queue and a second identical task will now be triggered. The result may be, for example, interleaved output to a file which is probably not what you intended.<br />
<br />
==Code snippets==<br />
<br />
===File Association===<br />
To add icons to file associations and register for use with a program use the [[FileAssociation]] component. If FileAssociation component for some reason doesn't works for you, or you need to run it as administrator for all users without elevating your application, an Inno Setup Script will fit your needs best. See [[Inno_Setup_Usage#File_Association]].<br />
<br />
===Ensure only a single instance can run===<br />
<br />
To ensure only a single instance of your program can run, you can use the [[UniqueInstance]] component which supports Windows and Linux (note that macOS prevents the same application from running more than once by default).<br />
<br />
Alternatively, you can use the mutex unit below which also supports Windows and Linux: <br />
<br />
<syntaxhighlight lang="pascal"><br />
{Author: Serguei Tarassov (from https://arbinada.com/en/node/1426)}<br />
<br />
unit mutex;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
type<br />
TMutex = class<br />
private<br />
FFileHandle: integer;<br />
public<br />
constructor Create(const AName: string; const WaitForMSec: integer = 10000);<br />
destructor Destroy; override;<br />
end;<br />
<br />
implementation<br />
<br />
uses<br />
Classes, SysUtils, DateUtils,<br />
{$IFDEF WINDOWS}<br />
Windows<br />
{$ENDIF};<br />
<br />
function GetTempDir: string;<br />
begin<br />
{$IFDEF WINDOWS}<br />
SetLength(Result, 255);<br />
SetLength(Result, GetTempPath(255, (PChar(Result))));<br />
{$ENDIF}<br />
{$IFDEF LINUX}<br />
Result := GetEnv('TMPDIR');<br />
if Result = '' then<br />
Result := '/tmp/'<br />
else if Result[Length(Result)] <> PathDelim then<br />
Result := Result + PathDelim;<br />
{$ENDIF}<br />
end;<br />
<br />
constructor TMutex.Create(const AName: string; const WaitForMSec: integer);<br />
function NextAttempt(const MaxTime: TDateTime): boolean;<br />
begin<br />
Sleep(1);<br />
Result := Now < MaxTime;<br />
end;<br />
<br />
var<br />
MaxTime: TDateTime;<br />
LockFileName: string;<br />
begin<br />
inherited Create;<br />
LockFileName := IncludeTrailingPathDelimiter(GetTempDir) + AName + '.tmp';<br />
MaxTime := IncMillisecond(Now, WaitForMSec);<br />
repeat<br />
if FileExists(LockFileName) then<br />
FFileHandle := FileOpen(LockFileName, fmShareExclusive)<br />
else<br />
FFileHandle := FileCreate(LockFileName, fmShareExclusive);<br />
until (FFileHandle <> -1) or not NextAttempt(MaxTime);<br />
if FFileHandle = -1 then<br />
raise Exception.CreateFmt('Unable to lock mutex (File: %s; waiting: %d msec)', [LockFileName, WaitForMSec]);<br />
end;<br />
<br />
destructor TMutex.Destroy;<br />
begin<br />
if FFileHandle <> -1 then<br />
FileClose(FFileHandle);<br />
inherited;<br />
end;<br />
<br />
end. <br />
</syntaxhighlight><br />
<br />
To use it, add in your project file:<br />
<br />
<syntaxhighlight lang="pascal"><br />
{$IFDEF WINDOWS}<br />
var<br />
MyMutex: TMutex;<br />
{$ENDIF}<br />
begin<br />
Application.Title := 'My App';<br />
<br />
{$IFDEF WINDOWS}<br />
Try<br />
MyMutex := TMutex.Create('MyAppMutex', 100);<br />
Except<br />
ShowMessage(Application.Title + ' is already running.');<br />
MyMutex.Free;<br />
Exit;<br />
End;<br />
{$ENDIF}<br />
<br />
Application.Initialize;<br />
Application.CreateForm(TForm1, Form1);<br />
Application.Run;<br />
<br />
{$IFDEF WINDOWS}<br />
MyMutex.Free;<br />
{$ENDIF}<br />
end. <br />
</syntaxhighlight><br />
<br />
===Showing Memory, Disk Space Information===<br />
<br />
<syntaxhighlight lang="pascal"><br />
...<br />
Uses<br />
Windows;<br />
...<br />
<br />
procedure TForm1.MemoryClick(Sender: TObject);<br />
Var<br />
Memory: TMemoryStatus;<br />
<br />
begin<br />
InfoMemo.Text := '';<br />
<br />
Memory.dwLength := SizeOf(Memory);<br />
GlobalMemoryStatus(Memory);<br />
<br />
InfoMemo.Lines.Add(Format('Memory total: %f GB', [Memory.dwTotalPhys /1024 /1024 /1024]));<br />
InfoMemo.Lines.Add(Format('Memory free: %f GB', [Memory.dwAvailPhys /1024 /1024 /1024]));<br />
InfoMemo.Lines.Add(Format('Memory in use: %d%%', [Memory.dwMemoryLoad]));<br />
InfoMemo.Lines.Add(Format('Pagefile size: %f GB', [Memory.dwTotalPageFile /1024 /1024 /1024]));<br />
InfoMemo.Lines.Add(Format('Pagefile free: %f GB', [Memory.dwAvailPageFile /1024 /1024 /1024]));<br />
InfoMemo.Lines.Add(Format('Virtual memory total: %f GB', [Memory.dwTotalVirtual /1024 /1024 /1024]));<br />
InfoMemo.Lines.Add(Format('Virtual memory free: %f GB', [Memory.dwAvailVirtual /1024 /1024 /1024]));<br />
InfoMemo.Lines.Add(Format('Disk space total: %f GB', [DiskSize(0) /1024 /1024 /1024]));<br />
InfoMemo.Lines.Add(Format('Disk space free: %f GB', [DiskFree(0) /1024 /1024 /1024])); <br />
end;<br />
</syntaxhighlight><br />
<br />
===Using Windows native wininet for web retrieval===<br />
<br />
<syntaxhighlight lang="pascal"><br />
{$IFDEF WINDOWS}<br />
// Need to use Windows WinInet to avoid issue with HTTPS<br />
// needing two OpenSSL DLLs to be provided with application<br />
// if using TFPHttpClient.<br />
// The WinINet API also gets any connection and proxy settings<br />
// set by Internet Explorer. Blessing or curse?<br />
<br />
function GetWebPage(const Url: string): string;<br />
var<br />
NetHandle: HINTERNET;<br />
UrlHandle: HINTERNET;<br />
Buffer: array[0..1023] of Byte;<br />
BytesRead: dWord;<br />
StrBuffer: UTF8String;<br />
begin<br />
Result := '';<br />
BytesRead := Default(dWord);<br />
NetHandle := InternetOpen('Mozilla/5.0(compatible; WinInet)', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);<br />
<br />
// NetHandle valid?<br />
if Assigned(NetHandle) then<br />
Try<br />
UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);<br />
<br />
// UrlHandle valid?<br />
if Assigned(UrlHandle) then<br />
Try<br />
repeat<br />
InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);<br />
SetString(StrBuffer, PAnsiChar(@Buffer[0]), BytesRead);<br />
Result := Result + StrBuffer;<br />
until BytesRead = 0;<br />
Finally<br />
InternetCloseHandle(UrlHandle);<br />
end<br />
// o/w UrlHandle invalid<br />
else<br />
ShowMessage('Cannot open URL: ' + Url);<br />
Finally<br />
InternetCloseHandle(NetHandle);<br />
end<br />
// NetHandle invalid<br />
else<br />
raise Exception.Create('Unable to initialize WinInet');<br />
end;<br />
{$ENDIF} <br />
</syntaxhighlight><br />
<br />
===Listing all available drives===<br />
<br />
<syntaxhighlight lang="pascal"><br />
program listdevices;<br />
<br />
{$ifdef fpc}{$mode delphi}{$endif}<br />
{$apptype console}<br />
<br />
uses<br />
Windows;<br />
<br />
var<br />
Drive: Char;<br />
DriveLetter: string;<br />
OldMode: Word; <br />
begin<br />
WriteLn('The following drives were found in this computer:');<br />
WriteLn('');<br />
<br />
// Empty Floppy or Zip drives can generate a Windows error.<br />
// We disable system errors during the listing.<br />
// Note that another way to skip these errors would be to use DEVICE_IO_CONTROL.<br />
OldMode := SetErrorMode(SEM_FAILCRITICALERRORS);<br />
try <br />
<br />
// Search all drive letters<br />
for Drive := 'A' to 'Z' do<br />
begin<br />
DriveLetter := Drive + ':\';<br />
<br />
case GetDriveType(PChar(DriveLetter)) of<br />
DRIVE_REMOVABLE: WriteLn(DriveLetter + ' Floppy Drive');<br />
DRIVE_FIXED: WriteLn(DriveLetter + ' Fixed Drive');<br />
DRIVE_REMOTE: WriteLn(DriveLetter + ' Network Drive');<br />
DRIVE_CDROM: WriteLn(DriveLetter + ' CD-ROM Drive');<br />
DRIVE_RAMDISK: WriteLn(DriveLetter + ' RAM Disk');<br />
end;<br />
end;<br />
<br />
finally<br />
// Restores previous Windows error mode.<br />
SetErrorMode(OldMode); <br />
end;<br />
<br />
// Also add a stop to see the result under Windows<br />
WriteLn('');<br />
WriteLn('Please press <ENTER> to exit the program.');<br />
ReadLn(DriveLetter);<br />
end.<br />
</syntaxhighlight><br />
<br />
===Creating a shortcut (.lnk) file===<br />
Creating a shortcut on the desktop (can be easily adapted to any location). Adapted from [http://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg13325.html post by Felipe Monteiro de Carvalho]<br />
The ISLink object has more methods that you can use to modify your shortcut...<br />
<br />
<syntaxhighlight lang="pascal"><br />
uses<br />
...<br />
windows, shlobj {for special folders}, ActiveX, ComObj;<br />
...<br />
procedure CreateDesktopShortCut(Target, TargetArguments, ShortcutName: string);<br />
var<br />
IObject: IUnknown;<br />
ISLink: IShellLink;<br />
IPFile: IPersistFile;<br />
PIDL: PItemIDList;<br />
InFolder: array[0..MAX_PATH] of Char;<br />
TargetName: String;<br />
LinkName: WideString;<br />
begin<br />
{ Creates an instance of IShellLink }<br />
IObject := CreateComObject(CLSID_ShellLink);<br />
ISLink := IObject as IShellLink;<br />
IPFile := IObject as IPersistFile;<br />
<br />
ISLink.SetPath(pChar(Target));<br />
ISLink.SetArguments(pChar(TargetArguments));<br />
ISLink.SetWorkingDirectory(pChar(ExtractFilePath(Target)));<br />
<br />
{ Get the desktop location }<br />
SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, PIDL);<br />
SHGetPathFromIDList(PIDL, InFolder);<br />
LinkName := InFolder + PathDelim + ShortcutName+'.lnk';<br />
<br />
{ Create the link }<br />
IPFile.Save(PWChar(LinkName), false);<br />
end;<br />
<br />
</syntaxhighlight><br />
<br />
===Getting special folders (My documents, Desktop, local application data, etc)===<br />
Often it is useful to get the location of a special folder such as the desktop. The example below shows how you can get the LocalAppData directory - where you can store user-specific configuration file files etc for your programs.<br />
<br />
Use the MyDocuments folder (or a subfolder) to store documents.<br />
<br />
Look in the [http://delphi-miranda-plugins.googlecode.com/svn-history/r105/trunk/FPC/units/src/shlobj.pp shlobj] unit (note: link may not be up to date) for more defines that let you look up the Desktop (note: use CSIDL_DESKTOPDIRECTORY, not CSIDL_DESKTOP), Recycle Bin, etc.<br />
<syntaxhighlight lang="pascal"><br />
uses <br />
...<br />
shlobj;<br />
<br />
var<br />
AppDataPath: Array[0..MaxPathLen] of Char; //Allocate memory<br />
...<br />
begin<br />
...<br />
AppDataPath:='';<br />
SHGetSpecialFolderPath(0,AppDataPath,CSIDL_LOCAL_APPDATA,false);<br />
writeln('Your local appdata path is: ' + AppDataPath);<br />
</syntaxhighlight><br />
<br />
Another way to achieve the task without using the Windows API is to query a specific environment variable. This solution allows to write a more homogeneous system code since depending on the OS, only the variable name has to be changed.<br />
<br />
For example:<br />
<syntaxhighlight lang="pascal"><br />
program UseEnv;<br />
<br />
uses sysutils;<br />
<br />
begin<br />
writeln(GetEnvironmentVariable('APPDATA'));<br />
writeln(GetEnvironmentVariable('PROGRAMFILES'));<br />
writeln(GetEnvironmentVariable('HOMEPATH'));<br />
readln;<br />
end. <br />
</syntaxhighlight><br />
<br />
However this solution is not always as accurate as '''SHGetSpecialFolderPath()''', since it is sometimes necessary to compose between several variables.<br />
<br />
The available variables can be retrieved with '''GetEnvironmentString()''':<br />
<br />
<syntaxhighlight lang="pascal"><br />
program ListEnv;<br />
<br />
uses sysutils;<br />
<br />
var<br />
i: integer;<br />
<br />
begin<br />
for i in [0..GetEnvironmentVariableCount-1] do<br />
writeln(GetEnvironmentString(i));<br />
readln;<br />
end. <br />
</syntaxhighlight><br />
<br />
===Enabling and disabling devices===<br />
The following code can be used to enable and disable Windows devices; it is useful to e.g. reset a serial port or USB device. An example program follows below.<br />
<syntaxhighlight lang="pascal"><br />
unit controlwindevice;<br />
<br />
{ Enable Disable windows devices<br />
<br />
Copyright (c) 2010-2012 Ludo Brands<br />
<br />
Permission is hereby granted, free of charge, to any person obtaining a copy<br />
of this software and associated documentation files (the "Software"), to<br />
deal in the Software without restriction, including without limitation the<br />
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or<br />
sell copies of the Software, and to permit persons to whom the Software is<br />
furnished to do so, subject to the following conditions:<br />
<br />
The above copyright notice and this permission notice shall be included in<br />
all copies or substantial portions of the Software.<br />
<br />
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br />
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br />
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE<br />
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br />
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br />
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br />
IN THE SOFTWARE.<br />
}<br />
<br />
<br />
{$mode delphi}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Classes, SysUtils,dynlibs,windows;<br />
<br />
const<br />
GUID_DEVCLASS_NET : TGUID = '{4D36E972-E325-11CE-BFC1-08002BE10318}';<br />
GUID_DEVCLASS_PORT : TGUID = '{4D36E978-E325-11CE-BFC1-08002BE10318}';<br />
<br />
type<br />
TDeviceControlResult=(DCROK,DCRErrEnumDeviceInfo,DCRErrSetClassInstallParams,<br />
DCRErrDIF_PROPERTYCHANGE);<br />
<br />
function LoadDevices(GUID_DevClass:TGUID):TStringList;<br />
function EnableDevice(SelectedItem: DWord):TDeviceControlResult;<br />
function DisableDevice(SelectedItem: DWord):TDeviceControlResult;<br />
<br />
implementation<br />
<br />
// Setup api, based on SetupApi.pas JEDI library<br />
const<br />
DIF_PROPERTYCHANGE = $00000012;<br />
DICS_ENABLE = $00000001;<br />
DICS_DISABLE = $00000002;<br />
DICS_FLAG_GLOBAL = $00000001; // make change in all hardware profiles<br />
DIGCF_PRESENT = $00000002;<br />
SPDRP_DEVICEDESC = $00000000; // DeviceDesc (R/W)<br />
SPDRP_CLASS = $00000007; // Class (R--tied to ClassGUID)<br />
SPDRP_CLASSGUID = $00000008; // ClassGUID (R/W)<br />
SPDRP_FRIENDLYNAME = $0000000C; // FriendlyName (R/W)<br />
<br />
type<br />
HDEVINFO = Pointer;<br />
DI_FUNCTION = LongWord; // Function type for device installer<br />
<br />
PSPClassInstallHeader = ^TSPClassInstallHeader;<br />
SP_CLASSINSTALL_HEADER = packed record<br />
cbSize: DWORD;<br />
InstallFunction: DI_FUNCTION;<br />
end;<br />
TSPClassInstallHeader = SP_CLASSINSTALL_HEADER;<br />
<br />
PSPPropChangeParams = ^TSPPropChangeParams;<br />
SP_PROPCHANGE_PARAMS = packed record<br />
ClassInstallHeader: TSPClassInstallHeader;<br />
StateChange: DWORD;<br />
Scope: DWORD;<br />
HwProfile: DWORD;<br />
end;<br />
TSPPropChangeParams = SP_PROPCHANGE_PARAMS;<br />
<br />
PSPDevInfoData = ^TSPDevInfoData;<br />
SP_DEVINFO_DATA = packed record<br />
cbSize: DWORD;<br />
ClassGuid: TGUID;<br />
DevInst: DWORD; // DEVINST handle<br />
Reserved: ULONG_PTR;<br />
end;<br />
TSPDevInfoData = SP_DEVINFO_DATA;<br />
<br />
TSetupDiEnumDeviceInfo = function(DeviceInfoSet: HDEVINFO;<br />
MemberIndex: DWORD; var DeviceInfoData: TSPDevInfoData): LongBool; stdcall;<br />
TSetupDiSetClassInstallParamsA = function(DeviceInfoSet: HDEVINFO;<br />
DeviceInfoData: PSPDevInfoData; ClassInstallParams: PSPClassInstallHeader;<br />
ClassInstallParamsSize: DWORD): LongBool; stdcall;<br />
TSetupDiSetClassInstallParamsW = function(DeviceInfoSet: HDEVINFO;<br />
DeviceInfoData: PSPDevInfoData; ClassInstallParams: PSPClassInstallHeader;<br />
ClassInstallParamsSize: DWORD): LongBool; stdcall;<br />
TSetupDiSetClassInstallParams = TSetupDiSetClassInstallParamsA;<br />
TSetupDiCallClassInstaller = function(InstallFunction: DI_FUNCTION;<br />
DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData): LongBool; stdcall;<br />
TSetupDiGetClassDevs = function(ClassGuid: PGUID; const Enumerator: PAnsiChar;<br />
hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall;<br />
TSetupDiGetDeviceRegistryPropertyA = function(DeviceInfoSet: HDEVINFO;<br />
const DeviceInfoData: TSPDevInfoData; Property_: DWORD;<br />
var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSize: DWORD;<br />
var RequiredSize: DWORD): BOOL; stdcall;<br />
TSetupDiGetDeviceRegistryPropertyW = function(DeviceInfoSet: HDEVINFO;<br />
const DeviceInfoData: TSPDevInfoData; Property_: DWORD;<br />
var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSize: DWORD;<br />
var RequiredSize: DWORD): BOOL; stdcall;<br />
TSetupDiGetDeviceRegistryProperty = TSetupDiGetDeviceRegistryPropertyA;<br />
<br />
var<br />
DevInfo: hDevInfo;<br />
SetupDiEnumDeviceInfo: TSetupDiEnumDeviceInfo;<br />
SetupDiSetClassInstallParams: TSetupDiSetClassInstallParams;<br />
SetupDiCallClassInstaller: TSetupDiCallClassInstaller;<br />
SetupDiGetClassDevs: TSetupDiGetClassDevs;<br />
SetupDiGetDeviceRegistryProperty: TSetupDiGetDeviceRegistryProperty;<br />
<br />
var<br />
SetupApiLoadCount:integer=0;<br />
<br />
function LoadSetupApi: Boolean;<br />
var SetupApiLib:TLibHandle;<br />
begin<br />
Result := True;<br />
Inc(SetupApiLoadCount);<br />
if SetupApiLoadCount > 1 then<br />
Exit;<br />
SetupApiLib:=LoadLibrary('SetupApi.dll');<br />
Result := SetupApiLib<>0;<br />
if Result then<br />
begin<br />
SetupDiEnumDeviceInfo := GetProcedureAddress(SetupApiLib, 'SetupDiEnumDeviceInfo');<br />
SetupDiSetClassInstallParams := GetProcedureAddress(SetupApiLib, 'SetupDiSetClassInstallParamsA');<br />
SetupDiCallClassInstaller := GetProcedureAddress(SetupApiLib, 'SetupDiCallClassInstaller');<br />
SetupDiGetClassDevs := GetProcedureAddress(SetupApiLib, 'SetupDiGetClassDevsA');<br />
SetupDiGetDeviceRegistryProperty := GetProcedureAddress(SetupApiLib, 'SetupDiGetDeviceRegistryPropertyA');<br />
end;<br />
end;<br />
<br />
// implementation<br />
<br />
function StateChange(NewState, SelectedItem: DWord;<br />
hDevInfo: hDevInfo): TDeviceControlResult;<br />
var<br />
PropChangeParams: TSPPropChangeParams;<br />
DeviceInfoData: TSPDevInfoData;<br />
begin<br />
PropChangeParams.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);<br />
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);<br />
// Get a handle to the Selected Item.<br />
if (not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, DeviceInfoData)) then<br />
begin<br />
Result := DCRErrEnumDeviceInfo;<br />
exit;<br />
end;<br />
// Set the PropChangeParams structure.<br />
PropChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;<br />
PropChangeParams.Scope := DICS_FLAG_GLOBAL;<br />
PropChangeParams.StateChange := NewState;<br />
if (not SetupDiSetClassInstallParams(hDevInfo, @DeviceInfoData,<br />
PSPClassInstallHeader(@PropChangeParams), SizeOf(PropChangeParams))) then<br />
begin<br />
Result := DCRErrSetClassInstallParams;<br />
exit;<br />
end;<br />
// Call the ClassInstaller and perform the change.<br />
if (not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, @DeviceInfoData)) then<br />
begin<br />
Result := DCRErrDIF_PROPERTYCHANGE;<br />
exit;<br />
end;<br />
Result := DCROK;<br />
end;<br />
<br />
function GetRegistryProperty(PnPHandle: HDEVINFO;<br />
DevData: TSPDevInfoData; Prop: DWORD; Buffer: PChar;<br />
dwLength: DWord): Boolean;<br />
var<br />
aBuffer: array[0..256] of Char;<br />
begin<br />
dwLength := 0;<br />
aBuffer[0] := #0;<br />
SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, Prop, Prop, PBYTE(@aBuffer[0]), SizeOf(aBuffer), dwLength);<br />
StrCopy(Buffer, aBuffer);<br />
Result := Buffer^ <> #0;<br />
end;<br />
<br />
function ConstructDeviceName(DeviceInfoSet: hDevInfo;<br />
DeviceInfoData: TSPDevInfoData; Buffer: PChar; dwLength: DWord): Boolean;<br />
const<br />
UnknownDevice = '<Unknown Device>';<br />
begin<br />
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_FRIENDLYNAME, Buffer, dwLength)) then<br />
begin<br />
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_DEVICEDESC, Buffer, dwLength)) then<br />
begin<br />
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_CLASS, Buffer, dwLength)) then<br />
begin<br />
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_CLASSGUID, Buffer, dwLength)) then<br />
begin<br />
dwLength := DWord(SizeOf(UnknownDevice));<br />
Buffer := Pointer(LocalAlloc(LPTR, Cardinal(dwLength)));<br />
StrCopy(Buffer, UnknownDevice);<br />
end;<br />
end;<br />
end;<br />
end;<br />
Result := true;<br />
end;<br />
<br />
<br />
function LoadDevices(GUID_DevClass:TGUID):TStringList;<br />
var<br />
DeviceInfoData: TSPDevInfoData;<br />
i: DWord;<br />
pszText: PChar;<br />
<br />
begin<br />
if (not LoadSetupAPI) then<br />
begin<br />
result:=nil;<br />
exit;<br />
end;<br />
DevInfo := nil;<br />
// Get a handle to all devices in all classes present on system<br />
DevInfo := SetupDiGetClassDevs(@GUID_DevClass, nil, 0, DIGCF_PRESENT);<br />
if (DevInfo = Pointer(INVALID_HANDLE_VALUE)) then<br />
begin<br />
result:=nil;<br />
exit;<br />
end;<br />
Result:=TStringList.Create;<br />
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);<br />
i := 0;<br />
// Enumerate though all the devices.<br />
while SetupDiEnumDeviceInfo(DevInfo, i, DeviceInfoData) do<br />
begin<br />
GetMem(pszText, 256);<br />
try<br />
// Get a friendly name for the device.<br />
ConstructDeviceName(DevInfo, DeviceInfoData, pszText, DWord(nil));<br />
Result.AddObject(pszText,Tobject(i));<br />
finally<br />
FreeMem(pszText);<br />
inc(i);<br />
end;<br />
end;<br />
end;<br />
<br />
function EnableDevice(SelectedItem: DWord):TDeviceControlResult;<br />
<br />
begin<br />
result:=StateChange(DICS_ENABLE, SelectedItem , DevInfo);<br />
end;<br />
<br />
function DisableDevice(SelectedItem: DWord):TDeviceControlResult;<br />
<br />
begin<br />
result:=StateChange(DICS_DISABLE, SelectedItem , DevInfo);<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
Example program that lists all ports preceeded by a number. <br />
<br />
Enter a number and the port will be disabled. Enter return again and the port will be enabled again.<br />
<syntaxhighlight lang="pascal"><br />
program devicetest;<br />
<br />
{$mode delphi}{$H+}<br />
<br />
uses<br />
Classes, controlwindevice;<br />
var<br />
sl:tstringlist;<br />
i:integer;<br />
begin<br />
sl:=Loaddevices(GUID_DEVCLASS_PORT);<br />
for i:=0 to sl.count-1 do<br />
writeln(i,' : ',sl[i]);<br />
readln(i);<br />
if DisableDevice(i)=DCROK then<br />
writeln(sl[i],' disabled');<br />
readln;<br />
if EnableDevice(i)=DCROK then<br />
writeln(sl[i],' enabled');<br />
sl.Free;<br />
readln;<br />
end.<br />
</syntaxhighlight><br />
<br />
===Downloading a file using urlmon===<br />
Urlmon.dll is built into Windows and can be used to e.g. download a file from a web site. It supports SSL/TLS connections.<br />
<br />
Windows-only; please look into libraries like [[fphttpclient]], [[Synapse]] and [[Indy]] for cross-platform solutions.<br />
<syntaxhighlight lang="pascal"><br />
function URLDownloadToFile(pCaller: pointer; URL: PChar; FileName: PChar; Reserved: DWORD; lpfnCB : pointer): HResult; stdcall; external 'urlmon.dll' name 'URLDownloadToFileA';<br />
<br />
procedure TForm1.Button1Click(Sender: TObject);<br />
var Source, Dest: string;<br />
begin<br />
Source:='http://lazarus.freepascal.org';<br />
Dest:='C:\Windows\temp\data.txt';<br />
if URLDownloadToFile(nil, PChar(Source), PChar(Dest), 0, nil)=0 then<br />
showmessage('Download ok!')<br />
else<br />
showMessage('Error downloading '+Source);<br />
end;<br />
</syntaxhighlight><br />
<br />
===Showing/finding processes===<br />
Use code like this to find a process handle based on the executable name (akin to the tasklist command):<br />
<br />
<syntaxhighlight lang="pascal"><br />
program ProcessFindPID;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
uses <br />
Classes, Sysutils, Windows, JwaTlHelp32;<br />
<br />
function QueryFullProcessImageNameW(hProcess: HANDLE; dwFlags: DWORD; lpExeName: LPTSTR;<br />
var lpdwSize: DWORD): BOOL; stdcall; external 'KERNEL32';<br />
<br />
function FindInProcesses(const PName: string): DWord;<br />
// Looks for process with PName executable and return<br />
var<br />
i: integer;<br />
CPID: DWORD;<br />
CProcName: array[0..259] of char;<br />
S: HANDLE;<br />
PE: TProcessEntry32;<br />
begin<br />
Result := 0;<br />
CProcName := '';<br />
S := CreateToolHelp32Snapshot(TH32CS_SNAPALL, 0); // Create snapshot<br />
PE.DWSize := SizeOf(PE); // Set size before use<br />
I := 1;<br />
if Process32First(S, PE) then<br />
repeat<br />
CProcName := PE.szExeFile;<br />
CPID := PE.th32ProcessID;<br />
//if CProcName = '' then Writeln(IntToStr(i) + ' - (' + IntToStr(CPID) + ') Failed to get a process name')<br />
Inc(i);<br />
if UpperCase(CProcName) = UpperCase(PName) then<br />
// Found the name. Set Result to the PID of process found<br />
Result := CPID;<br />
until not Process32Next(S, PE);<br />
CloseHandle(S);<br />
end;<br />
<br />
begin<br />
writeln('Explorer.exe has process id '+inttostr(FindInProcesses('explorer.exe')));<br />
end.<br />
</syntaxhighlight><br />
<br />
=== Identify Windows Version ===<br />
There is a code example at [[WindowsVersion]]<br />
<br />
<br></div>007https://wiki.freepascal.org/index.php?title=FileAssociation&diff=129937FileAssociation2019-12-22T14:18:40Z<p>007: </p>
<hr />
<div>{{FileAssociation}}<br />
<br />
{{Platform only|Windows|Windows|Windows}}<br />
== TFileAssociation ==<br />
<br />
Author: Lainz<br />
<br />
Licence: Modified LGPL<br />
<br />
Version: 1.0<br />
<br />
Description: This unit registers file association for Windows.<br />
<br />
== Download ==<br />
<br />
GitHub: https://github.com/lainz/FileAssociation<br />
<br />
== Usage ==<br />
<br />
First install the package. You can drop the component TFileAssociation (FileAssoc unit) that gets installed in the System tab of the IDE.<br />
<br />
<syntaxhighlight><br />
...<br />
uses<br />
...<br />
FileAssoc;//<-- add fileassociation unit here<br />
<br />
type<br />
<br />
...<br />
{ private declarations }<br />
assoc: TFileAssociation;<br />
...<br />
<br />
procedure TfrmMain.FormCreate(Sender: TObject);<br />
begin<br />
assoc := TFileAssociation.Create(Self);//<-- create like a regular component<br />
end;<br />
<br />
procedure TfrmMain.Button1Click(Sender: TObject);<br />
begin<br />
assoc.ApplicationName := 'Lazarus IDE';<br />
assoc.ApplicationDescription := 'RAD for Free Pascal';<br />
<br />
// you can change Extension and Action part for each extension you have<br />
<br />
assoc.Extension := '.lpr';<br />
assoc.ExtensionName := 'Lazarus Project';<br />
assoc.ExtensionIcon := '"C:\lazarus\images\lprfile.ico"';<br />
<br />
// full path required, you can use ParamStr(0) to get the path with the .exe name included. The path must be inside quotes if it has whitespace.<br />
assoc.Action := '"C:\lazarus\lazarus.exe" "%1"'; <br />
assoc.ActionName := 'Open';<br />
assoc.ActionIcon := '"C:\lazarus\images\mainicon.ico"';<br />
<br />
// notice that using RegisterForAllUsers as True requires Administrator Privileges<br />
// if you want to run without privileges set it to false, but it will register for current user only<br />
assoc.RegisterForAllUsers:=False;<br />
if assoc.Execute then<br />
begin<br />
ShowMessage('OK');<br />
assoc.ClearIconCache; //<<-- rebuild icons<br />
end;<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
== How to open the associated file ==<br />
<br />
<syntaxhighlight><br />
procedure TForm1.FormCreate(Sender: TObject);<br />
var<br />
s: String;<br />
begin<br />
// if there are parameters<br />
if ParamCount > 0 then<br />
begin<br />
// load the first parameter<br />
s := ParamStr(1);<br />
<br />
// if is a .txt file<br />
if ExtractFileExt(s) = '.txt' then<br />
begin<br />
// load the .txt file into a memo<br />
Memo1.Lines.LoadFromFile(s);<br />
end;<br />
end;<br />
end; <br />
</syntaxhighlight><br />
<br />
== See also ==<br />
<br />
If this component for some reason doesn't works for you, or you need to run it as administrator for all users without elevating your application, an Inno Setup Script will fit your needs best.<br />
<br />
[[Inno_Setup_Usage#File_Association]]</div>007https://wiki.freepascal.org/index.php?title=Nullable_types&diff=129705Nullable types2019-12-21T15:47:55Z<p>007: Added variant on see also</p>
<hr />
<div>{{Nullable types}}<br />
<br />
Nullable types are types which can have no value (can be unassigned).<br />
One such type in Pascal is [[Pointer]] type which can have [[Nil|<syntaxhighlight lang="pascal" enclose="none">nil</syntaxhighlight>]] value which means that it isn't assigned to any specific address.<br />
Same behavior can be implemented using [[Generics|generic types]] and advanced records with [[Operator overloading|operator overloading]].<br />
<br />
<syntaxhighlight lang="pascal"><br />
unit Nullable;<br />
<br />
{$mode delphi}{$H+}<br />
<br />
interface<br />
<br />
uses<br />
Classes, SysUtils;<br />
<br />
type<br />
TNullable<T> = record<br />
private<br />
FHasValue: Boolean;<br />
FValue: T;<br />
function GetValue: T;<br />
procedure SetValue(AValue: T);<br />
public<br />
procedure Clear;<br />
property HasValue: Boolean read FHasValue;<br />
property Value: T read GetValue write SetValue;<br />
class operator Implicit(A: T): TNullable<T>;<br />
class operator Implicit(A: Pointer): TNullable<T>;<br />
end;<br />
<br />
implementation<br />
<br />
{ TNullable }<br />
<br />
function TNullable<T>.GetValue: T;<br />
begin<br />
if FHasValue then<br />
Result := FValue<br />
else<br />
raise Exception.Create('Variable has no value');<br />
end;<br />
<br />
procedure TNullable<T>.SetValue(AValue: T);<br />
begin<br />
FValue := AValue;<br />
FHasValue := True;<br />
end;<br />
<br />
procedure TNullable<T>.Clear;<br />
begin<br />
FHasValue := False;<br />
end;<br />
<br />
class operator TNullable<T>.Implicit(A: T): TNullable<T>;<br />
begin<br />
Result.Value := A;<br />
end;<br />
<br />
class operator TNullable<T>.Implicit(A: Pointer): TNullable<T>;<br />
begin<br />
if A = nil then Result.Clear<br />
else raise Exception.Create('Pointer value not allowed');<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
Then you can define nullable types like:<br />
<syntaxhighlight lang="pascal"><br />
NullableChar = TNullable<Char>;<br />
NullableInteger = TNullable<Integer>;<br />
NullableString = TNullable<string>;<br />
</syntaxhighlight><br />
<br />
== See also ==<br />
* [[How to use nullable types]]<br />
<br />
The standard nullable type in Object Pascal is Variant.<br />
* [[Variant]]<br />
<br />
== External links ==<br />
<br />
* [https://www.arbinada.com/en/node/1439 Nullables in Free Pascal and Delphi]</div>007https://wiki.freepascal.org/index.php?title=FileAssociation&diff=129224FileAssociation2019-12-15T22:37:43Z<p>007: /* Usage */</p>
<hr />
<div>{{FileAssociation}}<br />
<br />
{{Platform only|Windows|Windows|Windows}}<br />
== TFileAssociation ==<br />
<br />
Author: Lainz<br />
<br />
Licence: Modified LGPL<br />
<br />
Version: 1.0<br />
<br />
Description: This unit registers file association for Windows.<br />
<br />
== Download ==<br />
<br />
GitHub: https://github.com/lainz/FileAssociation<br />
<br />
== Usage ==<br />
<br />
First install the package. You can drop the component TFileAssociation (FileAssoc unit) that gets installed in the System tab of the IDE.<br />
<br />
<syntaxhighlight><br />
...<br />
uses<br />
...<br />
FileAssoc;//<-- add fileassociation unit here<br />
<br />
type<br />
<br />
...<br />
{ private declarations }<br />
assoc: TFileAssociation;<br />
...<br />
<br />
procedure TfrmMain.FormCreate(Sender: TObject);<br />
begin<br />
assoc := TFileAssociation.Create(Self);//<-- create like a regular component<br />
end;<br />
<br />
procedure TfrmMain.Button1Click(Sender: TObject);<br />
begin<br />
assoc.ApplicationName := 'Lazarus IDE';<br />
assoc.ApplicationDescription := 'RAD for Free Pascal';<br />
<br />
// you can change Extension and Action part for each extension you have<br />
<br />
assoc.Extension := '.lpr';<br />
assoc.ExtensionName := 'Lazarus Project';<br />
assoc.ExtensionIcon := '"C:\lazarus\images\lprfile.ico"';<br />
<br />
// full path required, you can use ParamStr(0) to get the path with the .exe name included. The path must be inside quotes if it has whitespace.<br />
assoc.Action := '"C:\lazarus\lazarus.exe" "%1"'; <br />
assoc.ActionName := 'Open';<br />
assoc.ActionIcon := '"C:\lazarus\images\mainicon.ico"';<br />
<br />
// notice that using RegisterForAllUsers as True requires Administrator Privileges<br />
// if you want to run without privileges set it to false, but it will register for current user only<br />
assoc.RegisterForAllUsers:=False;<br />
if assoc.Execute then<br />
begin<br />
ShowMessage('OK');<br />
assoc.ClearIconCache; //<<-- rebuild icons<br />
end;<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
== How to open the associated file ==<br />
<br />
<syntaxhighlight><br />
procedure TForm1.FormCreate(Sender: TObject);<br />
var<br />
s: String;<br />
begin<br />
// if there are parameters<br />
if ParamCount > 0 then<br />
begin<br />
// load the first parameter<br />
s := ParamStr(1);<br />
<br />
// if is a .txt file<br />
if ExtractFileExt(s) = '.txt' then<br />
begin<br />
// load the .txt file into a memo<br />
Memo1.Lines.LoadFromFile(s);<br />
end;<br />
end;<br />
end; <br />
</syntaxhighlight></div>007https://wiki.freepascal.org/index.php?title=FileAssociation&diff=129220FileAssociation2019-12-15T22:06:17Z<p>007: /* Usage */</p>
<hr />
<div>{{FileAssociation}}<br />
<br />
{{Platform only|Windows|Windows|Windows}}<br />
== TFileAssociation ==<br />
<br />
Author: Lainz<br />
<br />
Licence: Modified LGPL<br />
<br />
Version: 1.0<br />
<br />
Description: This unit registers file association for Windows.<br />
<br />
== Download ==<br />
<br />
GitHub: https://github.com/lainz/FileAssociation<br />
<br />
== Usage ==<br />
<br />
First install the package. You can drop the component TFileAssociation (FileAssoc unit) that gets installed in the System tab of the IDE.<br />
<br />
<syntaxhighlight><br />
...<br />
uses<br />
...<br />
FileAssoc;//<-- add fileassociation unit here<br />
<br />
type<br />
<br />
...<br />
{ private declarations }<br />
assoc: TFileAssociation;<br />
...<br />
<br />
procedure TfrmMain.FormCreate(Sender: TObject);<br />
begin<br />
assoc := TFileAssociation.Create(Self);//<-- create like a regular component<br />
end;<br />
<br />
procedure TfrmMain.Button1Click(Sender: TObject);<br />
begin<br />
assoc.ApplicationName := 'Lazarus IDE';<br />
assoc.ApplicationDescription := 'RAD for Free Pascal';<br />
<br />
// you can change Extension and Action part for each extension you have<br />
<br />
assoc.Extension := '.lpr';<br />
assoc.ExtensionName := 'Lazarus Project';<br />
assoc.ExtensionIcon := '"C:\lazarus\images\lprfile.ico"';<br />
<br />
assoc.Action := '"C:\lazarus\lazarus.exe" "%1"';<br />
assoc.ActionName := 'Open';<br />
assoc.ActionIcon := '"C:\lazarus\images\mainicon.ico"';<br />
<br />
// notice that using RegisterForAllUsers as True requires Administrator Privileges<br />
// if you want to run without privileges set it to false, but it will register for current user only<br />
assoc.RegisterForAllUsers:=False;<br />
if assoc.Execute then<br />
begin<br />
ShowMessage('OK');<br />
assoc.ClearIconCache; //<<-- rebuild icons<br />
end;<br />
end;<br />
<br />
end.<br />
</syntaxhighlight><br />
<br />
== How to open the associated file ==<br />
<br />
<syntaxhighlight><br />
procedure TForm1.FormCreate(Sender: TObject);<br />
var<br />
s: String;<br />
begin<br />
// if there are parameters<br />
if ParamCount > 0 then<br />
begin<br />
// load the first parameter<br />
s := ParamStr(1);<br />
<br />
// if is a .txt file<br />
if ExtractFileExt(s) = '.txt' then<br />
begin<br />
// load the .txt file into a memo<br />
Memo1.Lines.LoadFromFile(s);<br />
end;<br />
end;<br />
end; <br />
</syntaxhighlight></div>007https://wiki.freepascal.org/index.php?title=FileAssociation&diff=129219FileAssociation2019-12-15T22:04:26Z<p>007: /* Usage */</p>
<hr />
<div>{{FileAssociation}}<br />
<br />
{{Platform only|Windows|Windows|Windows}}<br />
== TFileAssociation ==<br />
<br />
Author: Lainz<br />
<br />
Licence: Modified LGPL<br />
<br />
Version: 1.0<br />
<br />
Description: This unit registers file association for Windows.<br />
<br />
== Download ==<br />
<br />
GitHub: https://github.com/lainz/FileAssociation<br />
<br />
== Usage ==<br />
<br />
First install the package. You can drop the component TFileAssociation (FileAssoc unit) that gets installed in the System tab of the IDE.<br />
<br />
<syntaxhighlight><br />
...<br />
uses<br />
...<br />
FileAssoc;//<-- add fileassociation unit here<br />
<br />
type<br />
<br />
...<br />
{ private declarations }<br />
assoc: TFileAssociation;<br />
...<br />
<br />
procedure TfrmMain.FormCreate(Sender: TObject);<br />
begin<br />
assoc := TFileAssociation.Create(Self);//<-- create like a regular component<br />
end;<br />
<br />
procedure TfrmMain.Button1Click(Sender: TObject);<br />
begin<br />
assoc.ApplicationName := 'Lazarus IDE';<br />
assoc.ApplicationDescription := 'RAD for Free Pascal';<br />
<br />
// you can change Extension and Action part for each extension you have<br />
<br />
assoc.Extension := '.lpr';<br />
assoc.ExtensionName := 'Lazarus Project';<br />
assoc.ExtensionIcon := '"C:\lazarus\images\lprfile.ico"';<br />
<br />
assoc.Action := '"C:\lazarus\lazarus.exe" "%1"';<br />
assoc.ActionName := 'Open';<br />
assoc.ActionIcon := '"C:\lazarus\images\mainicon.ico"';<br />
<br />
// notice that using RegisterForAllUsers as True requires Administrator Privileges<br />
// if you want to run without privileges set it to false, but it will register for current user only<br />
assoc.RegisterForAllUsers:=False;<br />
if assoc.Execute then<br />
begin<br />
ShowMessage('OK');<br />
assoc.ClearIconCache; //<<-- rebuild icons<br />
end;<br />
end;<br />
<br />
end.<br />
</syntaxhighlight></div>007https://wiki.freepascal.org/index.php?title=fpWeb_Tutorial&diff=128543fpWeb Tutorial2019-11-19T01:55:55Z<p>007: /* Serving Static Files (Embedded Web Server) */</p>
<hr />
<div> Source: fcl-web tutorial (in pdf) by Leledumbo<br />
<br />
== Introduction ==<br />
<br />
fpWeb is a web application framework shipped by FPC in its default distribution as a part of fcl-web<br />
package. The framework itself is built on top of fcl-web features. The framework is built with RAD mind to<br />
make a good use of componentization in producing dynamic content. A Lazarus package is provided that<br />
can use the framework in a drag n drop manner for its session management and content production.<br />
This tutorial will attempt to cover basic functionality of fpWeb, so that one can build common web<br />
application with it. Note that this tutorial does '''NOT''' attempt to teach HTTP protocol, HTML, CSS, JavaScript<br />
or database manipulation as the protocol and client languages should be the prerequisites for every web<br />
application programmer and database manipulation does not differ from desktop implementation.<br />
<br />
== Architecture (PLEASE read) ==<br />
<br />
Before starting, it's necessary to know the architecture and application flow to avoid confusion when certain<br />
things don't work or work unexpectedly. So please spend some time reading this section.<br />
<br />
=== Application ===<br />
<br />
Application here refers to the protocol that your app will implement. fpWeb will happily switch from CGI,<br />
FCGI, Apache module to embedded server, and more if fcl-web implements another one in the future. Each<br />
application is implemented in its own unit, so to switch from one application to another, with the exception<br />
of Apache module, one just needs to change the respective identifier in the uses clause. Currently (as of<br />
3.0.0 / 3.1.1), they are:<br />
<br />
* fpCGI -> CGI<br />
* fpFCGI -> FastCGI<br />
* fpApache (requires httpd as well) -> Apache module<br />
* fpHttpApp -> embedded server<br />
<br />
Throughout this tutorial, we will use embedded server for the sake of simplicity because you don't have to<br />
deal with setting up virtual server and messing up with complicated configuration file and service<br />
management. Your app will be a single binary portable web application! Another reason would be there are<br />
more than just one web server application out there and each has different way to configure. It would be<br />
overkill to cover all of them while their documentation already does the job.<br />
Apache module is implemented as a (dynamic) library, while other protocols are normal application. Each<br />
application may have specific properties (such as port) available and meaningful only to that application.<br />
That's why if you look at fcl-web examples, .lpi / .lpr pairs for each protocol are put in their own directories,<br />
only the web modules are shared.<br />
<br />
=== Web Modules ===<br />
<br />
fpWeb applications consist of web modules which does the actual content production. Web module can<br />
contain web actions that can divide the functionality even more specific. For instance, an auth web module<br />
might have login and logout web actions. While an about web module might not need an action at all and<br />
serves just one content. Web module is integrated with fpTemplate that can be used for producing dynamic<br />
content from a template file. This is roughly similar to what PHP does, only the gap between logic and<br />
presentation is forced rather than suggested. Some say that fpTemplate implements passive view while PHP<br />
by default implements active view design pattern.<br />
<br />
== Installation ==<br />
<br />
The fpWeb package for Lazarus is not installed by default (but it's shipped), to enable fpWeb:<br />
# Open Lazarus and choose '''Package->Install/Uninstall Package''' <br />
# In the Available for installation listbox, look for '''weblaz''' and press '''Install selection'''. Press '''Save and rebuild IDE''' and confirm with '''Continue'''<br />
# Let the IDE rebuild and restart itself. If everything goes well, you should now have fpWeb tab in the component palette, as shown below:<br />
::[[File:fpwebtutorial_inst.png|Installed weblaz package]]<br />
<br />
== Hello, World! ==<br />
<br />
Let's create a simple Web Application. As commonly taught when learning programming, "Hello, World!" will be our first app.<br /><br /><br />
<br />
1. Open up Lazarus and choose '''Project->New Project''' then pick '''HTTP server Application'''<br />
:[[File:fpwebtutorial_create_app.png|Create new HTTP server application]]<br /><br />
<br />
2. Another dialog shall appear for serving static files, port selection and multithreading. Just use default port 8080.<br />
:<syntaxhighlight>You may skip the static files serving (go to tips and tricks section if you want to know it more).</syntaxhighlight><br />
: [[Image:fpwebtutorial_port_selection.PNG|Static files, port selection and multithreading options]]<br />
<br /><br />
:'''IMPORTANT!:'''<br />
:If you choose to use threads on *nix, don't forget to add cthreads as the first unit in the .lpr's uses clause, otherwise a RTE 232 will be generated. When running from console, a message shall appear:<br />
:<syntaxhighlight>This binary has no thread support compiled in. Recompile the application with a thread-driver in the program uses clause before other units using thread.</syntaxhighlight><br />
<br /><br />
3. Since Jan 14, 2017 (or FPC 3.0.4), you may need to open the .lpr and add the following line in the main body if it's not already there:<br />
:<syntaxhighlight>Application.LegacyRouting := true;</syntaxhighlight><br />
:reason will be explained in chapter [[#Routing]].<br />
<br /><br />
4. Whatever you choose, pick "OK" and you'll be presented in the default one module fpWeb app. <br /><br />
<br />
5. Focus the module and move to '''Object Inspector'''. Feel free to rename the module if you wish.<br /><br />
<br />
6. Choose '''Events''' tab and click the button at the right of the second column of the '''OnRequest''' row to create the event handler.<br />
:[[File:fpwebtutorial_on_request.png|Creating web module's OnRequest handler in the object inspector]]<br /><br />
<br />
:You will be redirected to the source editor with the following code:<br />
:<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
begin<br />
|<br />
end;</syntaxhighlight><br />
<br />
:Fill in the event with:<br />
<br />
:<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
begin<br />
AResponse.Content := 'Hello, World!';<br />
Handled := true;<br />
end;</syntaxhighlight><br /><br />
<br />
7. Then run your app (or press F9).<br /><br />
<br />
8. Open your browser and type:<br />
: http://localhost:8080/ <br /><br />
9. You should see "Hello, World!" displayed.<br /><br />
<br /><br />
<br />
If it doesn't, check below:<br />
<br />
* The framework does a lot of exception handling and the IDE's debugger might catch them and interrupts your app. It's OK to add most of the exceptions to the ignore list so you can concentrate more on your app flow. Keep skipping and continue until no more dialog appears and the browser shows the output.<br />
<br />
* '''Handled := true''' is the way we tell the framework that the request has been handled. Not setting it (or setting it to '''false''') will show error page instead. For now, this doesn't affect the request flow yet, but it will be later on. So keep it that way until the time comes to further make a good use of it.<br />
<br />
== Reading GET & POST data ==<br />
<br />
A dynamic content is likely to be triggered from user input, either through forms, providing values in the<br />
URL, etc. Those data are sent along the request, which is represented in the method as '''ARequest'''<br />
parameter of type '''TRequest'''.<br />
<br />
=== Reading GET ===<br />
<br />
GET data is provided as '''ARequest.QueryFields''' , which is a '''TStrings''' descendant. In short, whatever you<br />
usually do with TStrings, is applicable here such as accessing the data in a map style through the '''Values'''<br />
property.<br />
<br />
Reusing above code, replace the method body with:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
var<br />
LName: String;<br />
begin<br />
LName := ARequest.QueryFields.Values['Name'];<br />
if LName = EmptyStr then<br />
with AResponse.Contents do<br />
begin<br />
Add('<form action="' + ARequest.URI + '" method="GET"');<br />
Add('<label for="name">Please tell me your name:</label>');<br />
Add('<input type="text" name="name" id="name" />');<br />
Add('<input type="submit" value="Send" />');<br />
Add('</form>');<br />
end<br />
else<br />
AResponse.Content := 'Hello, ' + LName + '!';<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
'''ARequest.URI''' is just a convenience to refer to the current URI, so even when you change your registered<br />
module or action name, this code stays the same.<br />
<br />
Note that as in Pascal, referring to the data is done case insensitively.<br />
<br />
Now you can try requesting /, which will display<br />
Please tell me your name<br />
and /?name=<write anything here, e.g.: Bob>, which will display<br />
Hello, Bob!<br />
<br />
=== Reading POST ===<br />
<br />
POST is actually doesn't differ much from GET, only differs in which property to access. If GET is accessed<br />
through '''ARequest.QueryFields''' , POST is accessed through '''ARequest.ContentFields'''. POST style of<br />
previous code is:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
var<br />
LName: String;<br />
begin<br />
LName := ARequest.ContentFields.Values['Name'];<br />
if LName = EmptyStr then<br />
with AResponse.Contents do<br />
begin<br />
Add('<form action="' + ARequest.URI + '" method="POST"');<br />
Add('<label for="name">Please tell me your name:</label>');<br />
Add('<input type="text" name="name" id="name" />');<br />
Add('<input type="submit" value="Send" />');<br />
Add('</form>');<br />
end<br />
else<br />
AResponse.Content := 'Hello, ' + LName + '!';<br />
Handled := true;<br />
end;<br />
</syntaxhighlight><br />
<br />
=== Reading File Uploads ===<br />
<br />
One exception is for reading '''multipart/form-data''' fields, i.e. files. That one is available in<br />
'''ARequest.Files''' as a '''TUploadedFiles''' instance, which is a '''TCollection''' descendant. The following is<br />
TUploadedFiles public interface which you can use to access the files:<br />
<br />
<syntaxhighlight>TUploadedFiles = Class(TCollection)<br />
...<br />
public<br />
Function First: TUploadedFile;<br />
Function Last: TUploadedFile;<br />
Function IndexOfFile(AName: String) : Integer;<br />
Function FileByName(AName: String) : TUploadedFile;<br />
Function FindFile(AName: String) : TUploadedFile;<br />
Property Files[Index: Integer] : TUploadedFile read GetFile Write SetFile; default;<br />
end;</syntaxhighlight><br />
<br />
Each '''TUploadedFile''' itself has several properties:<br />
<br />
<syntaxhighlight>TUploadedFile = Class(TCollectionItem)<br />
...<br />
Public<br />
Destructor Destroy; override;<br />
Property FieldName: String Read FFieldName Write FFieldName;<br />
Property FileName: String Read FFileName Write FFileName;<br />
Property Stream: TStream Read GetStream;<br />
Property Size: Int64 Read FSize Write FSize;<br />
Property ContentType: String Read FContentType Write FContentType;<br />
Property Disposition: String Read FDisposition Write FDisposition;<br />
Property LocalFileName: String Read FLocalFileName Write FLocalFileName;<br />
Property Description: String Read FDescription Write FDescription;<br />
end;<br />
</syntaxhighlight><br />
<br />
They should be descriptive enough, with the exception of '''FileName''' and '''LocalFileName'''. '''FileName''' is<br />
the original file '''name''' as uploaded from client, '''LocalFileName''' is the file '''path''' in the server where the file<br />
is temporarily stored. Note the difference in bold terms above.<br />
<br />
Again, reusing the same request handler:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
var<br />
n: Integer;<br />
f: TUploadedFile;<br />
i: Integer;<br />
begin<br />
n := ARequest.Files.Count;<br />
if n = 0 then<br />
with AResponse.Contents do<br />
begin<br />
Add('<form id="form" action="' + ARequest.URI + '" method="POST" enctype="multipart/form-data">');<br />
Add('<label for="name">Drag n drop or click to add file:</label>');<br />
Add('<input type="file" name="input" />');<br />
Add('<input type="submit" value="Send" />');<br />
Add('</form>');<br />
end<br />
else<br />
begin<br />
f := ARequest.Files[0];<br />
AResponse.Contents.LoadFromStream(f.Stream);<br />
end;<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
drag n drop a file (preferably text, as it's will be rendered as text) to the input file field (or click the respective<br />
button) then click '''Send''' button. The file content should be displayed.<br />
<br />
== Cookies ==<br />
<br />
=== Setting ===<br />
<br />
Cookies are browser responsibility to save and keep, therefore server need to send it as part of the<br />
response in order to set one. '''AResponse.Cookies''' contains a list of cookies to be sent. It's a descendant of<br />
'''TCollection''', respectively the contained '''TCookie''' is a descendant of '''TCollectionItem'''. Therefore, you<br />
can use TCollection way of managing items to manipulate it.<br />
<br />
Here's an example:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
var<br />
C: TCookie;<br />
begin<br />
C := AResponse.Cookies.Add;<br />
C.Name := 'mycookie';<br />
C.Value := 'somevalue';<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
You won't see any output in your browser. But if you use some kind of developer tools (Chrome has one<br />
built-in), you can see the response header:<br />
<br />
[[File:fpwebtutorial_cookie_set.png|Set-Cookie response header in Chrome's developer tools]]<br />
<br />
Note that cookie has attributes, so Name and Value is not the only two you can set. Browse TCookie<br />
interface to see what properties are supported.<br />
<br />
=== Getting ===<br />
<br />
Once you give '''Set-Cookie''' header above, subsequent request to your site will contain additional header<br />
containing the value you ask to set previously:<br />
<br />
[[File:fpwebtutorial_cookie_get.png|Cookie request header in Chrome's developer tools]]<br />
<br />
Fortunately, the way to read it is no different from GET & POST data. The related property is<br />
'''ARequest.CookieFields'''. To read previously set cookie:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
begin<br />
AResponse.Contents.Add('<p>Cookie get: ' + ARequest.CookieFields.Values['mycookie'] + '</p>');<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
== Sessions ==<br />
<br />
TFPWebModule is a descendant of TSessionHTTPModule, so it has session management capability. Session<br />
is module based, so each module may choose to use or not to use session management.<br />
<br />
Session is implemented in abstract manner. By default, no implementation is provided. One sample<br />
implementation using .ini files is given in '''iniwebsession''' unit. You must have this unit in your project or<br />
implement one for session management to work. If you decide to implement one, basically you need to<br />
extend and implement abstract methods in '''TCustomSession''' and '''TSessionFactory''' classes.<br />
<br />
=== Activating ===<br />
<br />
To activate session management, set '''CreateSession''' property to true. Session will be started prior to<br />
request handling. In case of a new session, '''OnNewSession''' will be called. Initialize your session variables<br />
here.<br />
<br />
=== Session Variables Manipulation ===<br />
<br />
Session variables are provided as '''Session.Variables'''. This is a string to string map like structure, so you<br />
can read / write it like:<br />
<br />
<syntaxhighlight>Session.Variables['myvar'] := myvar; // write<br />
...<br />
myvar := Session.Variables['myvar']; // read</syntaxhighlight><br />
<br />
Setting a variable to empty string does '''NOT''' remove it. If you really want to remove a variable, call<br />
'''Session.RemoveVariable''' instead.<br />
<br />
=== Terminating ===<br />
<br />
Call '''Session.Terminate''' whenever you want to terminate a session (e.g.: user logout). Session will also<br />
automatically expire if the next request comes after '''Session.TimeOutMinutes''' since last request. When<br />
session terminates, '''OnSessionExpired''' will be called. Do whatever cleanup you need there.<br />
<br />
== Routing ==<br />
<br />
Since FPC 3.0.4, a new routing mechanism has been implemented. Instead of maintaining backward<br />
compatibility, it is decided that the new routing will be the default. Thus, any old code (or new code<br />
depending on old routing) must be ported by adding:<br />
<br />
<syntaxhighlight>Application.LegacyRouting := true;</syntaxhighlight><br />
<br />
in the .lpr.<br />
<br />
=== Old Mechanism ===<br />
<br />
==== Using Multiple Modules ====<br />
<br />
You can have multiple modules in your app. Click "File" menu, then click "New...". A dialog shall appear,<br />
select "Web Module" from the treeview.<br />
<br />
[[File:fpwebtutorial_new_module.png|Add new web module]]<br />
<br />
then click OK.<br />
<br />
<br />
With multiple modules exist in your app, you can no longer request just with /. The framework will not be<br />
able to magically select which module must serve the response, so there are two ways to state which<br />
module you'd like to call:<br />
<br />
* /<module name><br />
* /?module=<module name><br />
<br />
In the 2nd format, you can change "module" (which is the default value) to whatever valid query string key<br />
by modifying '''Application.ModuleVariable'''.<br />
<br />
==== Using Actions ====<br />
<br />
So far, we've only used web modules with single request handler. This doesn't scale much as your web app<br />
gets more and more complex. Moreover, some features might have shared properties and be better<br />
logically grouped, e.g.:<br />
<br />
* Account module<br />
** Login action<br />
** Logout action<br />
** Register action<br />
* Product module<br />
** Create action<br />
** Update action<br />
** Delete action<br />
** Details action<br />
<br />
===== Request Handling Flow =====<br />
<br />
Before using action, it is important to know fpWeb request handling flow. Failing to do so might render your<br />
action useless because it's always your data module that handles the request. How could that be? Going<br />
back a few chapters, remember the '''Handled := true''' that we always did before? Now this is where<br />
'''Handled''' parameter comes into play.<br />
<br />
'''Every''' requests will go through module's '''OnRequest''' first, regardless the requested action. Only if it does<br />
'''not''' set Handled to true, web action's OnRequest is executed.<br />
<br />
In general, the request flow is:<br />
<br />
[[File:fpwebtutorial_request_flow.png|fpWeb request flow]]<br />
<br />
Notice the "Our Concern" box, that's what we're going to put our attention at.<br />
<br />
===== Add Actions to Web Modules =====<br />
<br />
To add an action, select the web module then go to object inspector. In the properties tab, select Actions<br />
and click the button on the second column.<br />
<br />
[[File:fpwebtutorial_manage_actions.png|Manage actions button in object inspector]]<br />
<br />
A popup window shall appear where you can add, delete and reorder actions.<br />
<br />
[[File:fpwebtutorial_edit_actions.png|Manage actions button in popup window]]<br />
<br />
Press Add, a new action shall appear in the list. Select it then go to object inspector. It will currently show<br />
properties and events of that newly created action. Rename the Name property (this will be the name you<br />
write in the URL, so give it a short, simple but descriptive name) as you wish, I will choose "Hello". Move on<br />
to events tab, do the same as OnRequest for module, click button on the right of OnRequest row to create<br />
the request handler.<br />
<br />
[[File:fpwebtutorial_action_onrequest.png|Creating web action's OnRequest handler in the object inspector]]<br />
<br />
You will be presented in the same OnRequest interface, but this one handles web action instead of web<br />
module. Whatever you can do in web module's OnRequest can be done here as well. Copy the method body<br />
from the "Hello, World!" section.<br />
<br />
Remember to remove '''Handled := true''' from the previous web module's '''OnRequest''' body (or remove the<br />
event completely) for the action to take care of the request handling.<br />
<br />
Run your project, and fire up your browser. Now, since the request handling is delegated to web action, you<br />
can no longer just request /, but you need /<action name> or <Module's ActionVar property>=<action<br />
name>. Note that <Module's ActionVar property> has a default value of empty string, unlike<br />
'''Application.ModuleVariable''' which has "module" as the default value. So, by default, you can only use<br />
the /<action name> form.<br />
<br />
If you have multiple modules, then you have a variety of options:<br />
<br />
* /<module name>/<action name><br />
* /<module name>?action=<action name><br />
* /<action name>?module=<module name><br />
* /?module=<module name>&action=<action name><br />
<br />
Note that as soon as a module have at least one action, /<module or action name> alone will by default<br />
map to /<action name>. To change the behavior such that it maps to /<module name> by default, set<br />
'''Application.PreferModuleName''' to '''true'''. In case of multiple modules, if no module name given, then the<br />
default module will handle the given action. To change the behavior such that module name must be<br />
explicitly given, set '''Application.AllowDefaultModule''' to '''false'''.<br />
<br />
The following tables summarize what will happen based on the two properties:<br />
<br />
{| class="wikitable"<br />
!colspan="2" rowspan="2"|/<module or action name><br />
!colspan="2"|Application.PreferModuleName<br />
|-<br />
|true<br />
|false<br />
|-<br />
!rowspan="2"|Application.AllowDefaultModule<br />
|true<br />
|/<module name><br />
|/<default module>/<action name><br />
|-<br />
|false<br />
|/<module name><br />
|ERROR<br />
|}<br />
<br />
===== Default Action =====<br />
<br />
Remember the previous diagram, the "Delegate request handling to actions" is actually not so simple, but if<br />
we expand that diagram, the image will be too big to fit. So, here's the diagram of that part:<br />
<br />
[[File:fpwebtutorial_request_delegation_flow.png|Request delegation to action flow]]<br />
<br />
Two important things from the flow: DefActionWhenUnknown and a default action. The former is a web<br />
module's property while the latter corresponds to Default property of an action. In the latter case, in case<br />
there are more than two actions having Default property set to true, the the action order (as how it's<br />
shown in the manage actions popup window) will be considered to decide which is the default action. The<br />
two properties forms what the application should do if no matching action found for a given request.<br />
<br />
The following tables summarize what will happen based on the two properties:<br />
<br />
{| class="wikitable"<br />
!colspan="2" rowspan="2"|Request with invalid action name<br />
!colspan="2"|DefActionWhenUnknown<br />
|-<br />
|true<br />
|false<br />
|-<br />
!rowspan="2"|Action.Default<br />
|true<br />
|Request handled by default action<br />
|Error: No action found for action: <action name><br />
|-<br />
|false<br />
|Error: Invalid action name and no default action<br />
|Error: No action found for action: <action name><br />
|}<br />
<br />
<br />
{| class="wikitable"<br />
!colspan="2" rowspan="2"|Request without action name, i.e.: /<br />
!colspan="2"|DefActionWhenUnknown<br />
|-<br />
|true<br />
|false<br />
|-<br />
!rowspan="2"|Action.Default<br />
|true<br />
|Request handled by default action<br />
|Request handled by default action<br />
|-<br />
|false<br />
|Error: No action name and no default action<br />
|Error: No action name and no default action<br />
|}<br />
<br />
In case of error response above, a stack trace shall follow, complete with line number information if you<br />
build your app with -gl. We'll see later on how to create custom handler for this (stacktrace are no good for<br />
production). But for now, make sure you understand the concept of web module and web action, especially<br />
the request flow. Play around until you think you're ready for next section.<br />
<br />
=== New Mechanism ===<br />
<br />
The new mechanism is extremely flexible and works even without data modules (old mechanism only works<br />
with data modules).<br />
<br />
A dedicated unit for this routing is provided as '''httproute''' (add this to uses clause of program / unit where<br />
you want to register routes). The unit contains a function '''HTTPRouter''' that will return singleton object<br />
responsible for application's route management and has '''RegisterRoute''' method to register your route.<br />
<br />
==== Route Syntax ====<br />
<br />
The first parameter of '''HTTPRouter.RegisterRoute''' is the route that will be matched against incoming<br />
request. It can be as simple as '''*''' above, which means 0 or more paths or simply any paths, up to as<br />
complex as '''/api/v1/:resource/*''' which means '''REQUEST_URI''' header should start<br />
with '''/api/v1/''' followed by something else that will be bound to variable named resource and finally<br />
ended with 0 or more paths. It will match:<br />
<br />
* /api/v1/products<br />
* /api/v1/products/1<br />
* /api/v1/products/1/clone<br />
* /api/v1/products/something/else/that/is/really/long/and/silly<br />
<br />
but not:<br />
<br />
* /api/v1<br />
* /excuse/me/api/v1/products<br />
<br />
Basically there are only 3 special characters:<br />
* * denoting 0 or more paths<br />
* :param denoting a part<br />
* / denoting part separator<br />
<br />
your route will be composed of these 3 characters, plus everything else that made up a route. <br />
<br />
==== Registering a Route ====<br />
<br />
The 2nd, 3rd or 4th parameter (depending on whether you want to handle specific HTTP method and/or<br />
pass additional data to it) of '''HTTPRouter.RegisterRoute''' is overloaded with several possibilities:<br />
<br />
* Callback procedure<br />
<syntaxhighlight>TRouteCallback = Procedure(ARequest: TRequest; AResponse);</syntaxhighlight><br />
<br />
* Callback event<br />
<syntaxhighlight>TRouteEvent = Procedure(ARequest: TRequest; AResponse) of object;</syntaxhighlight><br />
<br />
* Object satisfying a (CORBA) interface<br />
<syntaxhighlight>IRouteInterface = Interface ['{10115353-10BA-4B00-FDA5-80B69AC4CAD0}']<br />
Procedure HandleRequest(ARequest: TRequest; AResponse: TResponse);<br />
end;</syntaxhighlight><br />
<br />
* Object extending abstract router class<br />
<syntaxhighlight>TRouteObject = Class(TObject, IRouteInterface)<br />
Public<br />
Procedure HandleRequest(ARequest: TRequest; AResponse: TResponse); virtual; abstract;<br />
end;<br />
<br />
TRouteObjectClass = Class of TRouteObject;</syntaxhighlight><br />
<br />
By default, if 2nd parameter is not a '''TRouteMethod''', then all HTTP methods will match. Use one<br />
of '''rmUnknown, rmAll, rmGet, rmPost, rmPut, rmDelete, rmOptions, rmHead, rmTrace''' to match only a<br />
specific HTTP method.<br />
<br />
Registration order matters. If there are two or more routes matching the current request, the earlier<br />
registered one will handle it.<br />
<br />
In this new mechanism, standalone Hello, World! program can be as simple as:<br />
<br />
<syntaxhighlight>uses<br />
fphttpapp, httpdefs, httproute;<br />
procedure DoHello(ARequest:TRequest; AResponse : TResponse);<br />
begin<br />
AResponse.Content:='<html><body><h1>Hello,World!</h1></body></html>'<br />
end;<br />
<br />
begin<br />
HTTPRouter.RegisterRoute('*', @DoHello);<br />
Application.Port := 9000;<br />
Application.Initialize;<br />
Application.Run;<br />
end.</syntaxhighlight><br />
<br />
== Using Templates ==<br />
<br />
fpWeb has integrated support for FPTemplate, Free Pascal's generic templating engine. It doesn't have to be<br />
used from web application context, but with integrated support things will be easier a bit. At least the<br />
memory management can be ignored as the module will take care of it.<br />
<br />
There are two levels where one can use templates at: action and module. The full RAD support is<br />
incomplete, so you need to go down to hand coding at some points.<br />
<br />
There are two modes of operation: non-parameterized and parameterized. The active mode is controlled by<br />
'''AllowTagParams''' property, which should be obvious enough what value refers to what mode.<br />
<br />
Template string can be given from a file through '''FileName''' property or a direct string through '''Template'''<br />
property. Template.Template, I know it sounds weird :) If both are filled then FileName will take<br />
precedence.<br />
<br />
The two properties: '''StartDelimiter''' and '''EndDelimiter''' define how the engine should recognize a<br />
template tag. For instance, if you have:<br />
<br />
* StartDelimiter = '{+'<br />
* EndDelimiter = '+}'<br />
<br />
then a string '{+title+}' defines a template tag named 'title'. Note that spaces are significant, so '{+ title +}'<br />
defines a template tag named ' title ' instead of just 'title'.<br />
<br />
Special for parameterized mode, additional three properties: '''ParamStartDelimiter''', '''ParamEndDelimiter'''<br />
and '''ParamValueSeparator''' defines how the engine should recognize a template tag parameter. For<br />
instance, if you have:<br />
<br />
* ParamStartDelimiter = '[-'<br />
* ParamEndDelimiter = '-]'<br />
* ParamValueSeparator = '='<br />
<br />
then a string '{+data [-p=v-][-a=b-] +}' defines a template tag named 'data' with parameter 'p' of value 'v' and<br />
parameter 'a' of value 'b'. This can be used to pass template level parameter such as expected date format,<br />
header-row-footer for customizable output presentation, name of file, etc. you decide.<br />
<br />
As a consequence of different way of operation, the core event where the template works is different, too.<br />
Non-parameterized will use '''OnGetParam''' while the parameterized will use '''OnReplaceTag'''. The two has of<br />
course different interface:<br />
<br />
<syntaxhighlight>Type<br />
// OnGetParam: for simple template tag support only (ex: {Name})<br />
TGetParamEvent = Procedure(<br />
Sender: TObject;<br />
Const ParamName: String;<br />
Out AValue: String<br />
) Of Object;<br />
// OnReplaceTag: for tags with parameters support<br />
TReplaceTagEvent = Procedure(<br />
Sender: TObject;<br />
Const TagString: String;<br />
TagParams: TStringList;<br />
Out ReplaceText: String<br />
) Of Object;</syntaxhighlight><br />
<br />
In '''OnGetParam''', you check for '''ParamName''', then assign '''AValue''' accordingly. i.e., if you want tag 'title' to be<br />
replaced by 'My App', then fill in the method with:<br />
<br />
<syntaxhighlight>// use Trim() if you want the spaces around tag to be insignificant<br />
case Trim(ParamName) of<br />
'title': AValue := 'My App';<br />
else<br />
AValue := 'UNKNOWN';<br />
end;</syntaxhighlight><br />
<br />
In '''OnReplaceTag''', you check for '''TagString''' and optionally '''TagParams''', then assign '''ReplaceText'''<br />
accordingly. i.e., if you want tag 'datetime' to be replaced by current time with parameter 'datetimeformat'<br />
to specify how the date and time should be formatted, then fill in the method like this:<br />
<br />
<syntaxhighlight>// use Trim() if you want the spaces around tag to be insignificant<br />
case Trim(TagString) of<br />
'datetime': AValue := FormatDateTime(TagParams.Values['datetimeformat'],Now);<br />
else<br />
AValue := 'UNKNOWN';<br />
end;</syntaxhighlight><br />
<br />
=== At Action Level ===<br />
<br />
Create/select an action, then go to object inspector. You will see a subcomponent property named<br />
'''Template'''. This template is a normal '''TFPTemplate''' instance. Expand it and fill in the properties as<br />
explained above. Now go to Events tab, again expand '''Template''', you will see the two events. Fill the one<br />
based on your value of '''AllowTagParams''' property.<br />
<br />
NOTE: If your Lazarus cannot autocomplete the event, try writing the name manually in the edit box then<br />
click the ... button. This is a bug in present Lazarus which may be fixed in the future.<br />
<br />
At this level, template with a content is not automatically set as request handler. It might change in the<br />
future, but let's deal with its current state. Fill in '''OnRequest''' event of the action, then fill it with:<br />
<br />
<syntaxhighlight>with Actions.CurrentAction as TFPWebAction do<br />
begin<br />
AResponse.Content := Template.GetContent;<br />
end;<br />
Handled := true;</syntaxhighlight><br />
<br />
The cast is required since '''CurrentAction''' is of type '''TCustomWebAction''' instead of '''TFPWebAction'''.<br />
Without it, we can't access the '''Template''' property.<br />
<br />
=== At Module Level ===<br />
<br />
At module level, you currently have to do it by hand coding since no RAD support is implemented. The<br />
linked property is ModuleTemplate . This is however not a regular '''TFPTemplate''' instance, but special<br />
'''TFPWebTemplate''' class that's a descendant of it.<br />
<br />
The idea here is to have module provide a layout while the actions provide content, with the ability to<br />
provide additional variables. It's therefore a good idea to keep '''AllowTagParams''' as is and assign<br />
'''OnGetParam''' event **of the module** only. Do NOT assign '''OnGetParam''' of '''ModuleTemplate''' as it will<br />
'''never''' be called.<br />
<br />
A template tag named 'content' will be replaced automatically by what content produced by action,<br />
everything else is either replaced from internal template variables or from '''OnGetParam'''.<br />
<br />
=== Using Separated Template ===<br />
<br />
Despite the somewhat incomplete integration, nothing stops you from using fpTemplate (or any other<br />
templating solutions) manually, outside from the integrated support. This could even be better in some<br />
cases since it's modular.<br />
<br />
== Tips and Tricks ==<br />
<br />
=== Returning Different HTTP Response Code ===<br />
<br />
By default, fpWeb will return HTTP 200 OK to indicate successful request handling. This surely is not always<br />
the case, as user input might not be as what we expected. To do so, set '''AResponse.Code''' in your request<br />
handler to the code you want to return.<br />
<br />
=== Redirect Request to Different URL ===<br />
<br />
A common flow after a successful login is to redirect user to his account page. This can be done by calling<br />
AResponse.SendRedirect in your request handler, supplying the URL to redirect request to.<br />
<br />
=== Serving Static Files (Embedded Web Server) ===<br />
<br />
Remember the dialog in the [[#Hello, World!]] section after you select HTTP server Application? If you tick<br />
"Register location to serve files from" you can fill "Location" (the URI segment, must not contain any slashes)<br />
and "Directory" (physical directory in your computer, must exist at runtime) and the wizard will simply add:<br />
<br />
<syntaxhighlight>RegisterFileLocation('<Location>','<Directory>');</syntaxhighlight><br />
<br />
to the beginning of your .lpr and add the unit '''fpwebfile''' to the uses clause. You can actually do this by hand anytime and also register multiple times for<br />
different locations / directories. After this you can request '''/<Location>/<any filename under<br />
Directory>''' and it will be served automatically. Note that the mimetype of the file is determined by<br />
fpmimetypes. Call '''MimeTypes.LoadFromFile''' with your mime.types file in order to give correct mimetype<br />
based on its extension. Otherwise, the file will always be served as '''application/octet-stream''' which<br />
means the browser will download it instead of interpreting it (especially important for JavaScript and CSS<br />
files).<br />
<br />
You can grab a complete mime.types here http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?&view=co<br />
<br />
In Lazarus 2.0.6 or newer you must add at the top of your program the full path of the mime.types file<br />
<br />
<syntaxhighlight>begin<br />
MimeTypesFile := Application.Location + 'mime.txt'; <br />
</syntaxhighlight><br />
<br />
Take into consideration that the default path coming with the project is lib\$(TargetCPU)-$(TargetOS)<br />
<br />
For example httpproject\lib\i386-win32\mime.txt<br />
<br />
=== Centralize Management of Configuration and Modules ===<br />
<br />
By default, the program file (.lpr) is the one that contains protocol unit. This limits the ability to use<br />
'''Application''' object from other contexts such as from web modules. Fortunately, it's not difficult to<br />
refactor to have what we want. We remove '''RegisterHTTPModule''' calls from web modules' units and left<br />
out the .lpr to empty main block with single unit identifier in the uses clause, we name it: brokers. The unit<br />
contains:<br />
<br />
<syntaxhighlight>unit Brokers;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
{ $define cgi}<br />
{ $define fcgi}<br />
{$define httpapp}<br />
<br />
uses<br />
CustWeb;<br />
<br />
function GetApp: TCustomWebApplication; inline;<br />
<br />
implementation<br />
<br />
uses<br />
{$ifdef cgi}fpcgi{$endif}<br />
{$ifdef fcgi}fpfcgi{$endif}<br />
{$ifdef httpapp}fphttpapp{$endif}<br />
,webmodule1<br />
,webmodule2<br />
;<br />
<br />
function GetApp: TCustomWebApplication;<br />
begin<br />
Result := Application;<br />
end;<br />
<br />
initialization<br />
RegisterHTTPModule('wm1', TWebModule1);<br />
RegisterHTTPModule('wm2', TWebModule2);<br />
{$ifndef cgi}<br />
Application.Port := 2015;<br />
{$endif}<br />
Application.Initialize;<br />
Application.Run;<br />
end.</syntaxhighlight><br />
<br />
This way, we can control over web module registration and also provide an API to get '''Application''' object<br />
(casted as '''TCustomWebApplication'''), while still easily switch between protocol implementations, in a single<br />
place.<br />
<br />
=== Terminating Gracefully (FastCGI / Embedded Web Server) ===<br />
<br />
Instead of Ctrl+C-ing your app, there is a way for your app to terminate gracefully, doing whatever cleanup it<br />
needs, by calling '''Application.Terminate'''. You might need to use previous trick to easily access the<br />
'''Application''' object. A common implementation is to provide a specific password protected module /<br />
action that calls the Terminate method. You may choose whatever way you want, though.<br />
<br />
=== Custom Exception Handler ===<br />
<br />
To override the default exception handler, which prints stacktrace whenever an exception is raised (i.e.: on<br />
HTTP 404 or 500), and thus not good for production, you must assign<br />
'''Application.OnShowRequestException'''. This is a method so you will need to provide an object that<br />
implements the method and assign it by using the object. i.e.: if you have '''MyExceptionHandler''' as an<br />
object of '''TMyExceptionHandler''' which has '''MyShowRequestException''' method, you can assign it by:<br />
<br />
<syntaxhighlight>Application.OnShowRequestException := @MyExceptionHandler.MyShowRequestException;</syntaxhighlight><br />
<br />
don't forget to '''.Create()''' '''MyExceptionHandler''' BEFORE assigning above or you will get an<br />
'''EAccessViolation'''!<br />
<br />
=== Pure Hand Coding (No Form Designer Required) ===<br />
<br />
It's not a must to use Lazarus' form designer to write an fpWeb application. You can use pure hand coding<br />
technique to write it. The secret lies in the 3rd parameter of '''RegisterHTTPModule''' : '''SkipStreaming'''. When<br />
this parameter is set to true, fpWeb will not search for .lfm resource. Therefore everything must be<br />
manually handled: property settings, event handlers, action registration, etc.<br />
<br />
Note that it's logical to do what's usually done through object inspector in an overriden constructor. Inside<br />
it, call the inherited constructor supplying both AOwner and CreateMode as parameters. After that you can<br />
set properties, assign event handlers, etc. Example:<br />
<br />
<syntaxhighlight>type<br />
THelloWorldModule = class(TFPWebModule)<br />
constructor CreateNew(AOwner: TComponent; CreateMode: Integer); override;<br />
procedure Request(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
end;<br />
<br />
constructor THelloWorldModule.CreateNew(AOwner: TComponent; CreateMode: Integer);<br />
begin<br />
inherited CreateNew(AOwner,CreateMode);<br />
OnRequest := @Request;<br />
end;<br />
<br />
procedure THelloWorldModule.Request(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
begin<br />
AResponse.Content := 'Hello, World!';<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
<br />
<br />
[[Category:Tutorials]]<br />
[[Category:FPC]]<br />
[[Category:Lazarus]]<br />
[[Category:Networking]]</div>007https://wiki.freepascal.org/index.php?title=fpWeb_Tutorial&diff=128542fpWeb Tutorial2019-11-19T01:45:43Z<p>007: /* Serving Static Files (Embedded Web Server) */</p>
<hr />
<div> Source: fcl-web tutorial (in pdf) by Leledumbo<br />
<br />
== Introduction ==<br />
<br />
fpWeb is a web application framework shipped by FPC in its default distribution as a part of fcl-web<br />
package. The framework itself is built on top of fcl-web features. The framework is built with RAD mind to<br />
make a good use of componentization in producing dynamic content. A Lazarus package is provided that<br />
can use the framework in a drag n drop manner for its session management and content production.<br />
This tutorial will attempt to cover basic functionality of fpWeb, so that one can build common web<br />
application with it. Note that this tutorial does '''NOT''' attempt to teach HTTP protocol, HTML, CSS, JavaScript<br />
or database manipulation as the protocol and client languages should be the prerequisites for every web<br />
application programmer and database manipulation does not differ from desktop implementation.<br />
<br />
== Architecture (PLEASE read) ==<br />
<br />
Before starting, it's necessary to know the architecture and application flow to avoid confusion when certain<br />
things don't work or work unexpectedly. So please spend some time reading this section.<br />
<br />
=== Application ===<br />
<br />
Application here refers to the protocol that your app will implement. fpWeb will happily switch from CGI,<br />
FCGI, Apache module to embedded server, and more if fcl-web implements another one in the future. Each<br />
application is implemented in its own unit, so to switch from one application to another, with the exception<br />
of Apache module, one just needs to change the respective identifier in the uses clause. Currently (as of<br />
3.0.0 / 3.1.1), they are:<br />
<br />
* fpCGI -> CGI<br />
* fpFCGI -> FastCGI<br />
* fpApache (requires httpd as well) -> Apache module<br />
* fpHttpApp -> embedded server<br />
<br />
Throughout this tutorial, we will use embedded server for the sake of simplicity because you don't have to<br />
deal with setting up virtual server and messing up with complicated configuration file and service<br />
management. Your app will be a single binary portable web application! Another reason would be there are<br />
more than just one web server application out there and each has different way to configure. It would be<br />
overkill to cover all of them while their documentation already does the job.<br />
Apache module is implemented as a (dynamic) library, while other protocols are normal application. Each<br />
application may have specific properties (such as port) available and meaningful only to that application.<br />
That's why if you look at fcl-web examples, .lpi / .lpr pairs for each protocol are put in their own directories,<br />
only the web modules are shared.<br />
<br />
=== Web Modules ===<br />
<br />
fpWeb applications consist of web modules which does the actual content production. Web module can<br />
contain web actions that can divide the functionality even more specific. For instance, an auth web module<br />
might have login and logout web actions. While an about web module might not need an action at all and<br />
serves just one content. Web module is integrated with fpTemplate that can be used for producing dynamic<br />
content from a template file. This is roughly similar to what PHP does, only the gap between logic and<br />
presentation is forced rather than suggested. Some say that fpTemplate implements passive view while PHP<br />
by default implements active view design pattern.<br />
<br />
== Installation ==<br />
<br />
The fpWeb package for Lazarus is not installed by default (but it's shipped), to enable fpWeb:<br />
# Open Lazarus and choose '''Package->Install/Uninstall Package''' <br />
# In the Available for installation listbox, look for '''weblaz''' and press '''Install selection'''. Press '''Save and rebuild IDE''' and confirm with '''Continue'''<br />
# Let the IDE rebuild and restart itself. If everything goes well, you should now have fpWeb tab in the component palette, as shown below:<br />
::[[File:fpwebtutorial_inst.png|Installed weblaz package]]<br />
<br />
== Hello, World! ==<br />
<br />
Let's create a simple Web Application. As commonly taught when learning programming, "Hello, World!" will be our first app.<br /><br /><br />
<br />
1. Open up Lazarus and choose '''Project->New Project''' then pick '''HTTP server Application'''<br />
:[[File:fpwebtutorial_create_app.png|Create new HTTP server application]]<br /><br />
<br />
2. Another dialog shall appear for serving static files, port selection and multithreading. Just use default port 8080.<br />
:<syntaxhighlight>You may skip the static files serving (go to tips and tricks section if you want to know it more).</syntaxhighlight><br />
: [[Image:fpwebtutorial_port_selection.PNG|Static files, port selection and multithreading options]]<br />
<br /><br />
:'''IMPORTANT!:'''<br />
:If you choose to use threads on *nix, don't forget to add cthreads as the first unit in the .lpr's uses clause, otherwise a RTE 232 will be generated. When running from console, a message shall appear:<br />
:<syntaxhighlight>This binary has no thread support compiled in. Recompile the application with a thread-driver in the program uses clause before other units using thread.</syntaxhighlight><br />
<br /><br />
3. Since Jan 14, 2017 (or FPC 3.0.4), you may need to open the .lpr and add the following line in the main body if it's not already there:<br />
:<syntaxhighlight>Application.LegacyRouting := true;</syntaxhighlight><br />
:reason will be explained in chapter [[#Routing]].<br />
<br /><br />
4. Whatever you choose, pick "OK" and you'll be presented in the default one module fpWeb app. <br /><br />
<br />
5. Focus the module and move to '''Object Inspector'''. Feel free to rename the module if you wish.<br /><br />
<br />
6. Choose '''Events''' tab and click the button at the right of the second column of the '''OnRequest''' row to create the event handler.<br />
:[[File:fpwebtutorial_on_request.png|Creating web module's OnRequest handler in the object inspector]]<br /><br />
<br />
:You will be redirected to the source editor with the following code:<br />
:<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
begin<br />
|<br />
end;</syntaxhighlight><br />
<br />
:Fill in the event with:<br />
<br />
:<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
begin<br />
AResponse.Content := 'Hello, World!';<br />
Handled := true;<br />
end;</syntaxhighlight><br /><br />
<br />
7. Then run your app (or press F9).<br /><br />
<br />
8. Open your browser and type:<br />
: http://localhost:8080/ <br /><br />
9. You should see "Hello, World!" displayed.<br /><br />
<br /><br />
<br />
If it doesn't, check below:<br />
<br />
* The framework does a lot of exception handling and the IDE's debugger might catch them and interrupts your app. It's OK to add most of the exceptions to the ignore list so you can concentrate more on your app flow. Keep skipping and continue until no more dialog appears and the browser shows the output.<br />
<br />
* '''Handled := true''' is the way we tell the framework that the request has been handled. Not setting it (or setting it to '''false''') will show error page instead. For now, this doesn't affect the request flow yet, but it will be later on. So keep it that way until the time comes to further make a good use of it.<br />
<br />
== Reading GET & POST data ==<br />
<br />
A dynamic content is likely to be triggered from user input, either through forms, providing values in the<br />
URL, etc. Those data are sent along the request, which is represented in the method as '''ARequest'''<br />
parameter of type '''TRequest'''.<br />
<br />
=== Reading GET ===<br />
<br />
GET data is provided as '''ARequest.QueryFields''' , which is a '''TStrings''' descendant. In short, whatever you<br />
usually do with TStrings, is applicable here such as accessing the data in a map style through the '''Values'''<br />
property.<br />
<br />
Reusing above code, replace the method body with:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
var<br />
LName: String;<br />
begin<br />
LName := ARequest.QueryFields.Values['Name'];<br />
if LName = EmptyStr then<br />
with AResponse.Contents do<br />
begin<br />
Add('<form action="' + ARequest.URI + '" method="GET"');<br />
Add('<label for="name">Please tell me your name:</label>');<br />
Add('<input type="text" name="name" id="name" />');<br />
Add('<input type="submit" value="Send" />');<br />
Add('</form>');<br />
end<br />
else<br />
AResponse.Content := 'Hello, ' + LName + '!';<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
'''ARequest.URI''' is just a convenience to refer to the current URI, so even when you change your registered<br />
module or action name, this code stays the same.<br />
<br />
Note that as in Pascal, referring to the data is done case insensitively.<br />
<br />
Now you can try requesting /, which will display<br />
Please tell me your name<br />
and /?name=<write anything here, e.g.: Bob>, which will display<br />
Hello, Bob!<br />
<br />
=== Reading POST ===<br />
<br />
POST is actually doesn't differ much from GET, only differs in which property to access. If GET is accessed<br />
through '''ARequest.QueryFields''' , POST is accessed through '''ARequest.ContentFields'''. POST style of<br />
previous code is:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
var<br />
LName: String;<br />
begin<br />
LName := ARequest.ContentFields.Values['Name'];<br />
if LName = EmptyStr then<br />
with AResponse.Contents do<br />
begin<br />
Add('<form action="' + ARequest.URI + '" method="POST"');<br />
Add('<label for="name">Please tell me your name:</label>');<br />
Add('<input type="text" name="name" id="name" />');<br />
Add('<input type="submit" value="Send" />');<br />
Add('</form>');<br />
end<br />
else<br />
AResponse.Content := 'Hello, ' + LName + '!';<br />
Handled := true;<br />
end;<br />
</syntaxhighlight><br />
<br />
=== Reading File Uploads ===<br />
<br />
One exception is for reading '''multipart/form-data''' fields, i.e. files. That one is available in<br />
'''ARequest.Files''' as a '''TUploadedFiles''' instance, which is a '''TCollection''' descendant. The following is<br />
TUploadedFiles public interface which you can use to access the files:<br />
<br />
<syntaxhighlight>TUploadedFiles = Class(TCollection)<br />
...<br />
public<br />
Function First: TUploadedFile;<br />
Function Last: TUploadedFile;<br />
Function IndexOfFile(AName: String) : Integer;<br />
Function FileByName(AName: String) : TUploadedFile;<br />
Function FindFile(AName: String) : TUploadedFile;<br />
Property Files[Index: Integer] : TUploadedFile read GetFile Write SetFile; default;<br />
end;</syntaxhighlight><br />
<br />
Each '''TUploadedFile''' itself has several properties:<br />
<br />
<syntaxhighlight>TUploadedFile = Class(TCollectionItem)<br />
...<br />
Public<br />
Destructor Destroy; override;<br />
Property FieldName: String Read FFieldName Write FFieldName;<br />
Property FileName: String Read FFileName Write FFileName;<br />
Property Stream: TStream Read GetStream;<br />
Property Size: Int64 Read FSize Write FSize;<br />
Property ContentType: String Read FContentType Write FContentType;<br />
Property Disposition: String Read FDisposition Write FDisposition;<br />
Property LocalFileName: String Read FLocalFileName Write FLocalFileName;<br />
Property Description: String Read FDescription Write FDescription;<br />
end;<br />
</syntaxhighlight><br />
<br />
They should be descriptive enough, with the exception of '''FileName''' and '''LocalFileName'''. '''FileName''' is<br />
the original file '''name''' as uploaded from client, '''LocalFileName''' is the file '''path''' in the server where the file<br />
is temporarily stored. Note the difference in bold terms above.<br />
<br />
Again, reusing the same request handler:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
var<br />
n: Integer;<br />
f: TUploadedFile;<br />
i: Integer;<br />
begin<br />
n := ARequest.Files.Count;<br />
if n = 0 then<br />
with AResponse.Contents do<br />
begin<br />
Add('<form id="form" action="' + ARequest.URI + '" method="POST" enctype="multipart/form-data">');<br />
Add('<label for="name">Drag n drop or click to add file:</label>');<br />
Add('<input type="file" name="input" />');<br />
Add('<input type="submit" value="Send" />');<br />
Add('</form>');<br />
end<br />
else<br />
begin<br />
f := ARequest.Files[0];<br />
AResponse.Contents.LoadFromStream(f.Stream);<br />
end;<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
drag n drop a file (preferably text, as it's will be rendered as text) to the input file field (or click the respective<br />
button) then click '''Send''' button. The file content should be displayed.<br />
<br />
== Cookies ==<br />
<br />
=== Setting ===<br />
<br />
Cookies are browser responsibility to save and keep, therefore server need to send it as part of the<br />
response in order to set one. '''AResponse.Cookies''' contains a list of cookies to be sent. It's a descendant of<br />
'''TCollection''', respectively the contained '''TCookie''' is a descendant of '''TCollectionItem'''. Therefore, you<br />
can use TCollection way of managing items to manipulate it.<br />
<br />
Here's an example:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
var<br />
C: TCookie;<br />
begin<br />
C := AResponse.Cookies.Add;<br />
C.Name := 'mycookie';<br />
C.Value := 'somevalue';<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
You won't see any output in your browser. But if you use some kind of developer tools (Chrome has one<br />
built-in), you can see the response header:<br />
<br />
[[File:fpwebtutorial_cookie_set.png|Set-Cookie response header in Chrome's developer tools]]<br />
<br />
Note that cookie has attributes, so Name and Value is not the only two you can set. Browse TCookie<br />
interface to see what properties are supported.<br />
<br />
=== Getting ===<br />
<br />
Once you give '''Set-Cookie''' header above, subsequent request to your site will contain additional header<br />
containing the value you ask to set previously:<br />
<br />
[[File:fpwebtutorial_cookie_get.png|Cookie request header in Chrome's developer tools]]<br />
<br />
Fortunately, the way to read it is no different from GET & POST data. The related property is<br />
'''ARequest.CookieFields'''. To read previously set cookie:<br />
<br />
<syntaxhighlight>procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
begin<br />
AResponse.Contents.Add('<p>Cookie get: ' + ARequest.CookieFields.Values['mycookie'] + '</p>');<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
== Sessions ==<br />
<br />
TFPWebModule is a descendant of TSessionHTTPModule, so it has session management capability. Session<br />
is module based, so each module may choose to use or not to use session management.<br />
<br />
Session is implemented in abstract manner. By default, no implementation is provided. One sample<br />
implementation using .ini files is given in '''iniwebsession''' unit. You must have this unit in your project or<br />
implement one for session management to work. If you decide to implement one, basically you need to<br />
extend and implement abstract methods in '''TCustomSession''' and '''TSessionFactory''' classes.<br />
<br />
=== Activating ===<br />
<br />
To activate session management, set '''CreateSession''' property to true. Session will be started prior to<br />
request handling. In case of a new session, '''OnNewSession''' will be called. Initialize your session variables<br />
here.<br />
<br />
=== Session Variables Manipulation ===<br />
<br />
Session variables are provided as '''Session.Variables'''. This is a string to string map like structure, so you<br />
can read / write it like:<br />
<br />
<syntaxhighlight>Session.Variables['myvar'] := myvar; // write<br />
...<br />
myvar := Session.Variables['myvar']; // read</syntaxhighlight><br />
<br />
Setting a variable to empty string does '''NOT''' remove it. If you really want to remove a variable, call<br />
'''Session.RemoveVariable''' instead.<br />
<br />
=== Terminating ===<br />
<br />
Call '''Session.Terminate''' whenever you want to terminate a session (e.g.: user logout). Session will also<br />
automatically expire if the next request comes after '''Session.TimeOutMinutes''' since last request. When<br />
session terminates, '''OnSessionExpired''' will be called. Do whatever cleanup you need there.<br />
<br />
== Routing ==<br />
<br />
Since FPC 3.0.4, a new routing mechanism has been implemented. Instead of maintaining backward<br />
compatibility, it is decided that the new routing will be the default. Thus, any old code (or new code<br />
depending on old routing) must be ported by adding:<br />
<br />
<syntaxhighlight>Application.LegacyRouting := true;</syntaxhighlight><br />
<br />
in the .lpr.<br />
<br />
=== Old Mechanism ===<br />
<br />
==== Using Multiple Modules ====<br />
<br />
You can have multiple modules in your app. Click "File" menu, then click "New...". A dialog shall appear,<br />
select "Web Module" from the treeview.<br />
<br />
[[File:fpwebtutorial_new_module.png|Add new web module]]<br />
<br />
then click OK.<br />
<br />
<br />
With multiple modules exist in your app, you can no longer request just with /. The framework will not be<br />
able to magically select which module must serve the response, so there are two ways to state which<br />
module you'd like to call:<br />
<br />
* /<module name><br />
* /?module=<module name><br />
<br />
In the 2nd format, you can change "module" (which is the default value) to whatever valid query string key<br />
by modifying '''Application.ModuleVariable'''.<br />
<br />
==== Using Actions ====<br />
<br />
So far, we've only used web modules with single request handler. This doesn't scale much as your web app<br />
gets more and more complex. Moreover, some features might have shared properties and be better<br />
logically grouped, e.g.:<br />
<br />
* Account module<br />
** Login action<br />
** Logout action<br />
** Register action<br />
* Product module<br />
** Create action<br />
** Update action<br />
** Delete action<br />
** Details action<br />
<br />
===== Request Handling Flow =====<br />
<br />
Before using action, it is important to know fpWeb request handling flow. Failing to do so might render your<br />
action useless because it's always your data module that handles the request. How could that be? Going<br />
back a few chapters, remember the '''Handled := true''' that we always did before? Now this is where<br />
'''Handled''' parameter comes into play.<br />
<br />
'''Every''' requests will go through module's '''OnRequest''' first, regardless the requested action. Only if it does<br />
'''not''' set Handled to true, web action's OnRequest is executed.<br />
<br />
In general, the request flow is:<br />
<br />
[[File:fpwebtutorial_request_flow.png|fpWeb request flow]]<br />
<br />
Notice the "Our Concern" box, that's what we're going to put our attention at.<br />
<br />
===== Add Actions to Web Modules =====<br />
<br />
To add an action, select the web module then go to object inspector. In the properties tab, select Actions<br />
and click the button on the second column.<br />
<br />
[[File:fpwebtutorial_manage_actions.png|Manage actions button in object inspector]]<br />
<br />
A popup window shall appear where you can add, delete and reorder actions.<br />
<br />
[[File:fpwebtutorial_edit_actions.png|Manage actions button in popup window]]<br />
<br />
Press Add, a new action shall appear in the list. Select it then go to object inspector. It will currently show<br />
properties and events of that newly created action. Rename the Name property (this will be the name you<br />
write in the URL, so give it a short, simple but descriptive name) as you wish, I will choose "Hello". Move on<br />
to events tab, do the same as OnRequest for module, click button on the right of OnRequest row to create<br />
the request handler.<br />
<br />
[[File:fpwebtutorial_action_onrequest.png|Creating web action's OnRequest handler in the object inspector]]<br />
<br />
You will be presented in the same OnRequest interface, but this one handles web action instead of web<br />
module. Whatever you can do in web module's OnRequest can be done here as well. Copy the method body<br />
from the "Hello, World!" section.<br />
<br />
Remember to remove '''Handled := true''' from the previous web module's '''OnRequest''' body (or remove the<br />
event completely) for the action to take care of the request handling.<br />
<br />
Run your project, and fire up your browser. Now, since the request handling is delegated to web action, you<br />
can no longer just request /, but you need /<action name> or <Module's ActionVar property>=<action<br />
name>. Note that <Module's ActionVar property> has a default value of empty string, unlike<br />
'''Application.ModuleVariable''' which has "module" as the default value. So, by default, you can only use<br />
the /<action name> form.<br />
<br />
If you have multiple modules, then you have a variety of options:<br />
<br />
* /<module name>/<action name><br />
* /<module name>?action=<action name><br />
* /<action name>?module=<module name><br />
* /?module=<module name>&action=<action name><br />
<br />
Note that as soon as a module have at least one action, /<module or action name> alone will by default<br />
map to /<action name>. To change the behavior such that it maps to /<module name> by default, set<br />
'''Application.PreferModuleName''' to '''true'''. In case of multiple modules, if no module name given, then the<br />
default module will handle the given action. To change the behavior such that module name must be<br />
explicitly given, set '''Application.AllowDefaultModule''' to '''false'''.<br />
<br />
The following tables summarize what will happen based on the two properties:<br />
<br />
{| class="wikitable"<br />
!colspan="2" rowspan="2"|/<module or action name><br />
!colspan="2"|Application.PreferModuleName<br />
|-<br />
|true<br />
|false<br />
|-<br />
!rowspan="2"|Application.AllowDefaultModule<br />
|true<br />
|/<module name><br />
|/<default module>/<action name><br />
|-<br />
|false<br />
|/<module name><br />
|ERROR<br />
|}<br />
<br />
===== Default Action =====<br />
<br />
Remember the previous diagram, the "Delegate request handling to actions" is actually not so simple, but if<br />
we expand that diagram, the image will be too big to fit. So, here's the diagram of that part:<br />
<br />
[[File:fpwebtutorial_request_delegation_flow.png|Request delegation to action flow]]<br />
<br />
Two important things from the flow: DefActionWhenUnknown and a default action. The former is a web<br />
module's property while the latter corresponds to Default property of an action. In the latter case, in case<br />
there are more than two actions having Default property set to true, the the action order (as how it's<br />
shown in the manage actions popup window) will be considered to decide which is the default action. The<br />
two properties forms what the application should do if no matching action found for a given request.<br />
<br />
The following tables summarize what will happen based on the two properties:<br />
<br />
{| class="wikitable"<br />
!colspan="2" rowspan="2"|Request with invalid action name<br />
!colspan="2"|DefActionWhenUnknown<br />
|-<br />
|true<br />
|false<br />
|-<br />
!rowspan="2"|Action.Default<br />
|true<br />
|Request handled by default action<br />
|Error: No action found for action: <action name><br />
|-<br />
|false<br />
|Error: Invalid action name and no default action<br />
|Error: No action found for action: <action name><br />
|}<br />
<br />
<br />
{| class="wikitable"<br />
!colspan="2" rowspan="2"|Request without action name, i.e.: /<br />
!colspan="2"|DefActionWhenUnknown<br />
|-<br />
|true<br />
|false<br />
|-<br />
!rowspan="2"|Action.Default<br />
|true<br />
|Request handled by default action<br />
|Request handled by default action<br />
|-<br />
|false<br />
|Error: No action name and no default action<br />
|Error: No action name and no default action<br />
|}<br />
<br />
In case of error response above, a stack trace shall follow, complete with line number information if you<br />
build your app with -gl. We'll see later on how to create custom handler for this (stacktrace are no good for<br />
production). But for now, make sure you understand the concept of web module and web action, especially<br />
the request flow. Play around until you think you're ready for next section.<br />
<br />
=== New Mechanism ===<br />
<br />
The new mechanism is extremely flexible and works even without data modules (old mechanism only works<br />
with data modules).<br />
<br />
A dedicated unit for this routing is provided as '''httproute''' (add this to uses clause of program / unit where<br />
you want to register routes). The unit contains a function '''HTTPRouter''' that will return singleton object<br />
responsible for application's route management and has '''RegisterRoute''' method to register your route.<br />
<br />
==== Route Syntax ====<br />
<br />
The first parameter of '''HTTPRouter.RegisterRoute''' is the route that will be matched against incoming<br />
request. It can be as simple as '''*''' above, which means 0 or more paths or simply any paths, up to as<br />
complex as '''/api/v1/:resource/*''' which means '''REQUEST_URI''' header should start<br />
with '''/api/v1/''' followed by something else that will be bound to variable named resource and finally<br />
ended with 0 or more paths. It will match:<br />
<br />
* /api/v1/products<br />
* /api/v1/products/1<br />
* /api/v1/products/1/clone<br />
* /api/v1/products/something/else/that/is/really/long/and/silly<br />
<br />
but not:<br />
<br />
* /api/v1<br />
* /excuse/me/api/v1/products<br />
<br />
Basically there are only 3 special characters:<br />
* * denoting 0 or more paths<br />
* :param denoting a part<br />
* / denoting part separator<br />
<br />
your route will be composed of these 3 characters, plus everything else that made up a route. <br />
<br />
==== Registering a Route ====<br />
<br />
The 2nd, 3rd or 4th parameter (depending on whether you want to handle specific HTTP method and/or<br />
pass additional data to it) of '''HTTPRouter.RegisterRoute''' is overloaded with several possibilities:<br />
<br />
* Callback procedure<br />
<syntaxhighlight>TRouteCallback = Procedure(ARequest: TRequest; AResponse);</syntaxhighlight><br />
<br />
* Callback event<br />
<syntaxhighlight>TRouteEvent = Procedure(ARequest: TRequest; AResponse) of object;</syntaxhighlight><br />
<br />
* Object satisfying a (CORBA) interface<br />
<syntaxhighlight>IRouteInterface = Interface ['{10115353-10BA-4B00-FDA5-80B69AC4CAD0}']<br />
Procedure HandleRequest(ARequest: TRequest; AResponse: TResponse);<br />
end;</syntaxhighlight><br />
<br />
* Object extending abstract router class<br />
<syntaxhighlight>TRouteObject = Class(TObject, IRouteInterface)<br />
Public<br />
Procedure HandleRequest(ARequest: TRequest; AResponse: TResponse); virtual; abstract;<br />
end;<br />
<br />
TRouteObjectClass = Class of TRouteObject;</syntaxhighlight><br />
<br />
By default, if 2nd parameter is not a '''TRouteMethod''', then all HTTP methods will match. Use one<br />
of '''rmUnknown, rmAll, rmGet, rmPost, rmPut, rmDelete, rmOptions, rmHead, rmTrace''' to match only a<br />
specific HTTP method.<br />
<br />
Registration order matters. If there are two or more routes matching the current request, the earlier<br />
registered one will handle it.<br />
<br />
In this new mechanism, standalone Hello, World! program can be as simple as:<br />
<br />
<syntaxhighlight>uses<br />
fphttpapp, httpdefs, httproute;<br />
procedure DoHello(ARequest:TRequest; AResponse : TResponse);<br />
begin<br />
AResponse.Content:='<html><body><h1>Hello,World!</h1></body></html>'<br />
end;<br />
<br />
begin<br />
HTTPRouter.RegisterRoute('*', @DoHello);<br />
Application.Port := 9000;<br />
Application.Initialize;<br />
Application.Run;<br />
end.</syntaxhighlight><br />
<br />
== Using Templates ==<br />
<br />
fpWeb has integrated support for FPTemplate, Free Pascal's generic templating engine. It doesn't have to be<br />
used from web application context, but with integrated support things will be easier a bit. At least the<br />
memory management can be ignored as the module will take care of it.<br />
<br />
There are two levels where one can use templates at: action and module. The full RAD support is<br />
incomplete, so you need to go down to hand coding at some points.<br />
<br />
There are two modes of operation: non-parameterized and parameterized. The active mode is controlled by<br />
'''AllowTagParams''' property, which should be obvious enough what value refers to what mode.<br />
<br />
Template string can be given from a file through '''FileName''' property or a direct string through '''Template'''<br />
property. Template.Template, I know it sounds weird :) If both are filled then FileName will take<br />
precedence.<br />
<br />
The two properties: '''StartDelimiter''' and '''EndDelimiter''' define how the engine should recognize a<br />
template tag. For instance, if you have:<br />
<br />
* StartDelimiter = '{+'<br />
* EndDelimiter = '+}'<br />
<br />
then a string '{+title+}' defines a template tag named 'title'. Note that spaces are significant, so '{+ title +}'<br />
defines a template tag named ' title ' instead of just 'title'.<br />
<br />
Special for parameterized mode, additional three properties: '''ParamStartDelimiter''', '''ParamEndDelimiter'''<br />
and '''ParamValueSeparator''' defines how the engine should recognize a template tag parameter. For<br />
instance, if you have:<br />
<br />
* ParamStartDelimiter = '[-'<br />
* ParamEndDelimiter = '-]'<br />
* ParamValueSeparator = '='<br />
<br />
then a string '{+data [-p=v-][-a=b-] +}' defines a template tag named 'data' with parameter 'p' of value 'v' and<br />
parameter 'a' of value 'b'. This can be used to pass template level parameter such as expected date format,<br />
header-row-footer for customizable output presentation, name of file, etc. you decide.<br />
<br />
As a consequence of different way of operation, the core event where the template works is different, too.<br />
Non-parameterized will use '''OnGetParam''' while the parameterized will use '''OnReplaceTag'''. The two has of<br />
course different interface:<br />
<br />
<syntaxhighlight>Type<br />
// OnGetParam: for simple template tag support only (ex: {Name})<br />
TGetParamEvent = Procedure(<br />
Sender: TObject;<br />
Const ParamName: String;<br />
Out AValue: String<br />
) Of Object;<br />
// OnReplaceTag: for tags with parameters support<br />
TReplaceTagEvent = Procedure(<br />
Sender: TObject;<br />
Const TagString: String;<br />
TagParams: TStringList;<br />
Out ReplaceText: String<br />
) Of Object;</syntaxhighlight><br />
<br />
In '''OnGetParam''', you check for '''ParamName''', then assign '''AValue''' accordingly. i.e., if you want tag 'title' to be<br />
replaced by 'My App', then fill in the method with:<br />
<br />
<syntaxhighlight>// use Trim() if you want the spaces around tag to be insignificant<br />
case Trim(ParamName) of<br />
'title': AValue := 'My App';<br />
else<br />
AValue := 'UNKNOWN';<br />
end;</syntaxhighlight><br />
<br />
In '''OnReplaceTag''', you check for '''TagString''' and optionally '''TagParams''', then assign '''ReplaceText'''<br />
accordingly. i.e., if you want tag 'datetime' to be replaced by current time with parameter 'datetimeformat'<br />
to specify how the date and time should be formatted, then fill in the method like this:<br />
<br />
<syntaxhighlight>// use Trim() if you want the spaces around tag to be insignificant<br />
case Trim(TagString) of<br />
'datetime': AValue := FormatDateTime(TagParams.Values['datetimeformat'],Now);<br />
else<br />
AValue := 'UNKNOWN';<br />
end;</syntaxhighlight><br />
<br />
=== At Action Level ===<br />
<br />
Create/select an action, then go to object inspector. You will see a subcomponent property named<br />
'''Template'''. This template is a normal '''TFPTemplate''' instance. Expand it and fill in the properties as<br />
explained above. Now go to Events tab, again expand '''Template''', you will see the two events. Fill the one<br />
based on your value of '''AllowTagParams''' property.<br />
<br />
NOTE: If your Lazarus cannot autocomplete the event, try writing the name manually in the edit box then<br />
click the ... button. This is a bug in present Lazarus which may be fixed in the future.<br />
<br />
At this level, template with a content is not automatically set as request handler. It might change in the<br />
future, but let's deal with its current state. Fill in '''OnRequest''' event of the action, then fill it with:<br />
<br />
<syntaxhighlight>with Actions.CurrentAction as TFPWebAction do<br />
begin<br />
AResponse.Content := Template.GetContent;<br />
end;<br />
Handled := true;</syntaxhighlight><br />
<br />
The cast is required since '''CurrentAction''' is of type '''TCustomWebAction''' instead of '''TFPWebAction'''.<br />
Without it, we can't access the '''Template''' property.<br />
<br />
=== At Module Level ===<br />
<br />
At module level, you currently have to do it by hand coding since no RAD support is implemented. The<br />
linked property is ModuleTemplate . This is however not a regular '''TFPTemplate''' instance, but special<br />
'''TFPWebTemplate''' class that's a descendant of it.<br />
<br />
The idea here is to have module provide a layout while the actions provide content, with the ability to<br />
provide additional variables. It's therefore a good idea to keep '''AllowTagParams''' as is and assign<br />
'''OnGetParam''' event **of the module** only. Do NOT assign '''OnGetParam''' of '''ModuleTemplate''' as it will<br />
'''never''' be called.<br />
<br />
A template tag named 'content' will be replaced automatically by what content produced by action,<br />
everything else is either replaced from internal template variables or from '''OnGetParam'''.<br />
<br />
=== Using Separated Template ===<br />
<br />
Despite the somewhat incomplete integration, nothing stops you from using fpTemplate (or any other<br />
templating solutions) manually, outside from the integrated support. This could even be better in some<br />
cases since it's modular.<br />
<br />
== Tips and Tricks ==<br />
<br />
=== Returning Different HTTP Response Code ===<br />
<br />
By default, fpWeb will return HTTP 200 OK to indicate successful request handling. This surely is not always<br />
the case, as user input might not be as what we expected. To do so, set '''AResponse.Code''' in your request<br />
handler to the code you want to return.<br />
<br />
=== Redirect Request to Different URL ===<br />
<br />
A common flow after a successful login is to redirect user to his account page. This can be done by calling<br />
AResponse.SendRedirect in your request handler, supplying the URL to redirect request to.<br />
<br />
=== Serving Static Files (Embedded Web Server) ===<br />
<br />
Remember the dialog in the [[#Hello, World!]] section after you select HTTP server Application? If you tick<br />
"Register location to serve files from" you can fill "Location" (the URI segment, must not contain any slashes)<br />
and "Directory" (physical directory in your computer, must exist at runtime) and the wizard will simply add:<br />
<br />
<syntaxhighlight>RegisterFileLocation('<Location>','<Directory>');</syntaxhighlight><br />
<br />
to the beginning of your .lpr and add the unit '''fpwebfile''' to the uses clause. You can actually do this by hand anytime and also register multiple times for<br />
different locations / directories. After this you can request '''/<Location>/<any filename under<br />
Directory>''' and it will be served automatically. Note that the mimetype of the file is determined by<br />
fpmimetypes. Call '''MimeTypes.LoadFromFile''' with your mime.types file in order to give correct mimetype<br />
based on its extension. Otherwise, the file will always be served as '''application/octet-stream''' which<br />
means the browser will download it instead of interpreting it (especially important for JavaScript and CSS<br />
files).<br />
<br />
You can grab a complete mime.types here http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?&view=co<br />
<br />
=== Centralize Management of Configuration and Modules ===<br />
<br />
By default, the program file (.lpr) is the one that contains protocol unit. This limits the ability to use<br />
'''Application''' object from other contexts such as from web modules. Fortunately, it's not difficult to<br />
refactor to have what we want. We remove '''RegisterHTTPModule''' calls from web modules' units and left<br />
out the .lpr to empty main block with single unit identifier in the uses clause, we name it: brokers. The unit<br />
contains:<br />
<br />
<syntaxhighlight>unit Brokers;<br />
<br />
{$mode objfpc}{$H+}<br />
<br />
interface<br />
<br />
{ $define cgi}<br />
{ $define fcgi}<br />
{$define httpapp}<br />
<br />
uses<br />
CustWeb;<br />
<br />
function GetApp: TCustomWebApplication; inline;<br />
<br />
implementation<br />
<br />
uses<br />
{$ifdef cgi}fpcgi{$endif}<br />
{$ifdef fcgi}fpfcgi{$endif}<br />
{$ifdef httpapp}fphttpapp{$endif}<br />
,webmodule1<br />
,webmodule2<br />
;<br />
<br />
function GetApp: TCustomWebApplication;<br />
begin<br />
Result := Application;<br />
end;<br />
<br />
initialization<br />
RegisterHTTPModule('wm1', TWebModule1);<br />
RegisterHTTPModule('wm2', TWebModule2);<br />
{$ifndef cgi}<br />
Application.Port := 2015;<br />
{$endif}<br />
Application.Initialize;<br />
Application.Run;<br />
end.</syntaxhighlight><br />
<br />
This way, we can control over web module registration and also provide an API to get '''Application''' object<br />
(casted as '''TCustomWebApplication'''), while still easily switch between protocol implementations, in a single<br />
place.<br />
<br />
=== Terminating Gracefully (FastCGI / Embedded Web Server) ===<br />
<br />
Instead of Ctrl+C-ing your app, there is a way for your app to terminate gracefully, doing whatever cleanup it<br />
needs, by calling '''Application.Terminate'''. You might need to use previous trick to easily access the<br />
'''Application''' object. A common implementation is to provide a specific password protected module /<br />
action that calls the Terminate method. You may choose whatever way you want, though.<br />
<br />
=== Custom Exception Handler ===<br />
<br />
To override the default exception handler, which prints stacktrace whenever an exception is raised (i.e.: on<br />
HTTP 404 or 500), and thus not good for production, you must assign<br />
'''Application.OnShowRequestException'''. This is a method so you will need to provide an object that<br />
implements the method and assign it by using the object. i.e.: if you have '''MyExceptionHandler''' as an<br />
object of '''TMyExceptionHandler''' which has '''MyShowRequestException''' method, you can assign it by:<br />
<br />
<syntaxhighlight>Application.OnShowRequestException := @MyExceptionHandler.MyShowRequestException;</syntaxhighlight><br />
<br />
don't forget to '''.Create()''' '''MyExceptionHandler''' BEFORE assigning above or you will get an<br />
'''EAccessViolation'''!<br />
<br />
=== Pure Hand Coding (No Form Designer Required) ===<br />
<br />
It's not a must to use Lazarus' form designer to write an fpWeb application. You can use pure hand coding<br />
technique to write it. The secret lies in the 3rd parameter of '''RegisterHTTPModule''' : '''SkipStreaming'''. When<br />
this parameter is set to true, fpWeb will not search for .lfm resource. Therefore everything must be<br />
manually handled: property settings, event handlers, action registration, etc.<br />
<br />
Note that it's logical to do what's usually done through object inspector in an overriden constructor. Inside<br />
it, call the inherited constructor supplying both AOwner and CreateMode as parameters. After that you can<br />
set properties, assign event handlers, etc. Example:<br />
<br />
<syntaxhighlight>type<br />
THelloWorldModule = class(TFPWebModule)<br />
constructor CreateNew(AOwner: TComponent; CreateMode: Integer); override;<br />
procedure Request(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
end;<br />
<br />
constructor THelloWorldModule.CreateNew(AOwner: TComponent; CreateMode: Integer);<br />
begin<br />
inherited CreateNew(AOwner,CreateMode);<br />
OnRequest := @Request;<br />
end;<br />
<br />
procedure THelloWorldModule.Request(Sender: TObject; ARequest: TRequest;<br />
AResponse: TResponse; var Handled: Boolean);<br />
begin<br />
AResponse.Content := 'Hello, World!';<br />
Handled := true;<br />
end;</syntaxhighlight><br />
<br />
<br />
<br />
[[Category:Tutorials]]<br />
[[Category:FPC]]<br />
[[Category:Lazarus]]<br />
[[Category:Networking]]</div>007https://wiki.freepascal.org/index.php?title=pas2js&diff=128286pas2js2019-11-05T13:46:42Z<p>007: Undo revision 128285 by 007 (talk)</p>
<hr />
<div>{{Translate}}<br />
<br />
__TOC__<br />
= Pas2js : What is it ? =<br />
<br />
== Compiler ==<br />
Pas2js is an open source [[Pascal]] to [[JavaScript]] transpiler. It parses Object Pascal and emits JavaScript.<br />
The JavaScript is currently of level ECMAScript 5 and should run in any browser or in Node.js (target "nodejs").<br />
It is available in 3 forms:<br />
* as a library <br />
* as a command-line program<br />
* as a webserver<br />
<br />
It transpiles from actual Pascal source, it has no intermediate .ppu files. <br />
That means all sources must always be available.<br />
<br />
Through external class definitions, the compiler can use JavaScript classes:<br />
* All classes available in the JavaScript runtime, and in the browser are available <br/>through import units (comparable to the windows or unix units for the native compiler).<br />
* For Node.js, basic support for the nodejs runtime environment is available.<br />
* An import unit for jQuery is available (libjquery)<br />
<br />
As a non commercial open source project we are always searching for helping hands. If you want to contribute see [[Pas2js How to contribute|here]].<br />
<br />
This project is '''not''' related to a similar named project on github.<br />
<br />
== RTL ==<br />
For the generated code to work, a small JavaScript file is needed: rtl.js. It defines an object rtl.<br />
This object will start the Object Pascal code if you include a call to rtl.run() in the [[HTML]] page.<br />
<br />
<syntaxhighlight lang="html4strict"><br />
<script type="application/javascript"><br />
rtl.run()<br />
</script><br />
</syntaxhighlight><br />
pas2js can automatically include this file in the generated output, like this:<br />
<pre><br />
pas2js -Jc -Jirtl.js -Tbrowser hello.pas<br />
</pre><br />
For nodejs, the compiler will insert the call to rtl.run() automatically at the end of the generated Javascript file.<br />
<br />
There is a basic Object Pascal RTL, several units from the FPC Packages are also available<br />
* system<br />
* sysutils<br />
* Math<br />
* strutils<br />
* rtlconst<br />
* classes<br />
* contnrs<br />
* DB (yes, TDataset)<br />
* fpcunit testsuite<br />
* custapp<br />
* restconnection<br />
* js (javascript system objects)<br />
* web (browser provided objects)<br />
* libjquery (jquery is available too)<br />
* nodejs (basic node runtime environment)<br />
* typinfo<br />
* objpas<br />
* browserconsole (support writeln)<br />
* dateutils<br />
* browserapp<br />
* nodejsapp<br />
<br />
= Where to get it =<br />
The pas2js compiler and RTL are - naturally - open source and can be downloaded and used freely.<br />
<br />
== Daily Snapshots == <br />
The daily snapshot directory contains binaries for Linux (64 bit) for trunk and latest fixes branch.<br />
Other OSes (macOS, linux) will be made available as time permits<br />
<br />
The snapshots are uploaded to<br />
* ftp://ftpmaster.freepascal.org/fpc/contrib/pas2js/snapshot<br />
<br />
== Releases == <br />
The releases contain binaries for Windows (32 and 64bit), Linux (64 bit) and MacOS.<br />
<br />
The releases are uploaded to<br />
* ftp://ftpmaster.freepascal.org/fpc/contrib/pas2js<br />
Every version has a directory with the version number.<br />
A list of changes can be found on the changelog page [[Pas2JS Version Changes]]<br />
<br />
Download the latest release for your operating system and unpack it in folder of your choice. The example below uses C:\lazarus\pas2js. The release contains three folders:<br />
* bin - contains the compiler as executable (pas2js or pas2js.exe) and library and some utilities.<br />
* demo - lots of examples<br />
* packages - the Pascal units of the RTL and other packages.<br />
<br />
You can create a simple config to let the compiler find the RTL and packages.<br />
<br />
bin/pas2js.cfg<br />
<br />
<pre><br />
#<br />
# Minimal config file for pas2js compiler<br />
#<br />
# -d is the same as #DEFINE<br />
# -u is the same as #UNDEF<br />
#<br />
# Write always a nice logo ;)<br />
-l<br />
<br />
# Display Hints, Warnings and Notes<br />
-vwnh<br />
# If you don't want so much verbosity use<br />
#-vw<br />
<br />
# Allow C-operators<br />
-Sc<br />
<br />
-Fu$CfgDir\..\packages\*<br />
<br />
#IFDEF nodejs<br />
-Jirtl.js<br />
#ENDIF<br />
<br />
# end.<br />
</pre><br />
<br />
== SVN ==<br />
<br />
<syntaxhighlight lang="bash"><br />
svn co https://svn.freepascal.org/svn/projects/pas2js/trunk pas2js<br />
</syntaxhighlight><br />
<br />
You need [[FPC]] 3.0.4 or better to compile it.<br />
<br />
Change to the directory and build it with:<br />
<br />
<syntaxhighlight lang="bash"><br />
make clean all<br />
</syntaxhighlight><br />
<br />
This creates ''bin/$(TargetCPU)-$(TargetOS)/pas2js'' (Windows: pas2js.exe). For example on Linux 64bit it creates ''bin/x86_64-linux/pas2js'', while under Windows 64bit it creates ''bin\x86_64-win\pas2js.exe''.<br />
<br />
= How to use pas2js =<br />
<br />
The command-line arguments are kept mostly the same as the FPC command-line arguments.<br />
Error messages are also in the same format.<br />
<br />
The compiler needs access to all sources, and so you need to specify the path to the sources of <br />
all used units. <br />
<br />
As for the FPC compiler, a configuration file is supported, which has the same syntax as the FPC config file. Note that the snapshots and svn version already contains a default pas2js.cfg with unit search paths (-Fu) for the rtl and fcl. See here how for details about the [[pas2js.cfg]].<br />
<br />
Basically, the command is the same as any FPC command line. The only thing that is different is the target: ''-Tbrowser'' or ''-Tnodeejs''<br />
<br />
Here is the complete list of [[pas2js command line arguments|command line arguments]].<br />
<br />
== for the browser ==<br />
Consider the classical:<br />
<syntaxhighlight lang="pascal"><br />
program hello;<br />
<br />
begin<br />
Writeln('Hello, world!');<br />
end.<br />
</syntaxhighlight><br />
Yes, writeln is supported. Here is how to compile it:<br />
<br />
<pre><br />
pas2js -Jc -Jirtl.js -Tbrowser hello.pas<br />
</pre><br />
When compiled succesfully, the code can be run in the browser by opening a html file in the browser with the following content:<br />
<syntaxhighlight lang="html4strict"><br />
<html><br />
<head><br />
<meta charset="utf-8"/><br />
<script type="application/javascript" src="hello.js"></script><br />
</head><br />
<body><br />
<script type="application/javascript"><br />
rtl.run();<br />
</script><br />
</body><br />
</html><br />
</syntaxhighlight><br />
The files that are needed are:<br />
* hello.html<br />
* hello.js<br />
Whether hello.html is opened by double-clicking it in the explorer or put on a server and opened with an URL, is not relevant for the functioning.<br />
<br />
The output is visible in the browser's web developer console.<br />
By including the browserconsole unit, it will be visible in the browser page:<br />
<syntaxhighlight lang="pascal"><br />
program hello;<br />
<br />
uses browserconsole;<br />
<br />
begin<br />
Writeln('Hello, world!');<br />
end.<br />
</syntaxhighlight><br />
<br />
== for NodeJS ==<br />
<pre><br />
pas2js -Tnodejs hello.pas<br />
</pre><br />
When compiled succesfully, the code can be run in node using the following command.<br />
<pre><br />
nodejs hello.js<br />
</pre><br />
<br />
Note: on MacOS it is "node hello.js"<br />
<br />
= Supported syntax elements =<br />
<br />
A significant amount of Object Pascal syntax is supported, including RTTI.<br />
A more detailed list can be found in the [https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/utils/pas2js/docs/translation.html?view=co translation.html].file in the sources.<br />
<br />
*[[Mode_Delphi|Delphi]] and [[Mode_ObjFPC|ObjFPC]] mode<br />
*[[Program]], [[Unit]]s, namespaces<br />
*unit initialization, but not finalization<br />
*[[Var]], [[Const]], [[Type]]<br />
*string (unicodestring), char (widechar), [[Boolean]], [[Double]], [[Byte]], [[Shortint]], [[Word]], [[Smallint]], longword, [[Longint]], nativeint(int53), nativeuint(int52), currency<br />
*resourcestrings<br />
*[[Pointer]] (as a reference to a class, array, record, pointer of record, interface, but no pointer arithmetic)<br />
*[[Record]] (but no variant records), advanced records (since 1.3)<br />
*[[Function]]s, [[Procedure]]s, nested, anonymous functions (since 1.1)<br />
*function types, of object, reference to (closures)<br />
*function arguments: default, const, var, out<br />
*[[If]]-then-else<br />
*[[For]]-do<br />
*[[Repeat]]-until<br />
*[[While]]-do<br />
*[[With]]-do<br />
*try-finally<br />
*try-except<br />
*enums<br />
*sets<br />
*arrays static, dynamic, open, multi dimensionals, array of const<br />
*String like array operations: ''a:=[1,2,3]+[1,1];''<br />
*class type, visibility, virtual, override, abstract, overload, properties, class properties, class var, class const, constructor, destructor, class constructor (since 1.5)<br />
*class-of<br />
*nested classes<br />
*interfaces: CORBA, COM, delegations, method resolution, reference counting, TVirtualInterface<br />
*external classes, vars, const<br />
*class helpers, record helpers, type helpers (since 1.3)<br />
*Enumeration for..in..do<br />
*Type alias, e.g. type TTranslateString = type string;<br />
*RTTI<br />
*asm block for embedding JavaScript directly<br />
*compiler directives (e.g. $ifdef, $if, $define, $modeswitch, $R+)<br />
*compile time and run time range and overflow checking<br />
*[https://wiki.freepascal.org/pas2js_Generics generics] <br />
<br />
There are some constructs that are naturally not supported and will never be supported:<br />
*Anything involving memory pointers and pointer arithmetic.<br />
*Variant records<br />
<br />
Details about supported elements and the conversion from Pascal to JavaScript: [https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/utils/pas2js/docs/translation.html?view=co translation].<br />
<br />
= Planned language features =<br />
Basically, the idea is to get the pas2js transpiler up to the same level as FPC or Delphi. <br />
That means the following needs to be added:<br />
* Extended RTTI<br />
* Operator Overloading<br />
<br />
Needless to say, anything requiring direct memory access is not going to be supported.<br />
<br />
= Other not implemented features =<br />
<br />
*Array of interface<br />
*Enums with custom values<br />
*Finalization sections, class destructors<br />
*Futures<br />
*Global properties<br />
*Inline<br />
*Library<br />
*Objects<br />
*Pointer arithmetic<br />
*Record field interface<br />
*Resources<br />
*Variant records<br />
*Variants<br />
<br />
= Lazarus integration of pas2js =<br />
<br />
Lazarus understands the concept of external classes as used by pas2js, so code completion will work.<br />
<br />
Since Lazarus 1.9 the IDE can use pas2js.exe as a normal compiler.<br />
<br />
The integration is described here: [[lazarus pas2js integration]].<br />
It is still under construction, but deep integration with lazarus is planned.<br />
<br />
= Importing Javascript classes =<br />
<br />
To import a javascript class, one writes a normal class definition that mimics the Javascript class.<br />
It is possible to use properties. Many examples can be found in the JS, web, nodejs and libjquery units.<br />
<br />
Here is a simple example:<br />
<syntaxhighlight lang="pascal"><br />
TJSFunction = class external name 'Function'(TJSObject)<br />
private<br />
Flength: NativeInt external name 'length';<br />
Fprototyp: TJSFunction external name 'prototyp';<br />
public<br />
name: String;<br />
property prototyp: TJSFunction read Fprototyp;<br />
property length: NativeInt read Flength;<br />
function apply(thisArg: TJSObject; const ArgArray: TJSValueDynArray): JSValue; varargs;<br />
function bind(thisArg: TJSObject): JSValue; varargs;<br />
function call(thisArg: TJSObject): JSValue; varargs;<br />
end;<br />
</syntaxhighlight><br />
<br />
This declares the <code>TJSFunction</code> object : in Javascript, functions are objects. <br />
* The "<code>external name 'Function'</code>" means that you declare a Javascript class where the Javascript name of the class is 'Function'.<br />
* The <code>(TJSObject)</code> means it descends from <code>TJSObject</code> also an external class. There does not need to be an ancestor type.<br />
* Fields are declared just as in Pascal.<br />
* To declare read-only fields, a trick can be used:</b> declare the field using an <var>external name "thename"</code> modifier, and declare a read-only property with the same name.<br>(see the length declaration)<br />
* <code>Varargs</code> can be used to indicate that a function accepts any number of arguments.<br />
* <code>JSValue</code> can be used to indicate an unknown type. <br/>It is more or less equivalent to a Variant.<br />
<br />
= Create simple JS objects with the new function =<br />
<br />
Some JS-framework functions expect an JS object as parameter. Here is how to do that in Pascal using the ''new'' function from unit ''JS'':<br />
<br />
<syntaxhighlight lang="javascript"><br />
// JavaScript:<br />
DoIt({name:"Fred", id:3, size:4.3});<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
// Pascal;<br />
DoIt(new(['name','Fred', 'id',3, 'size',4.3]));<br />
</syntaxhighlight><br />
<br />
You can nest it to create sub objects:<br />
<br />
<syntaxhighlight lang="javascript"><br />
// JavaScript:<br />
DoIt({name:"Fred", size:{width:3,height:2}});<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
// Pascal;<br />
DoIt(new(['name','Fred', 'size',new(['width',3, 'height',2])]));<br />
</syntaxhighlight><br />
<br />
You can use TJSArray._of to create JS arrays on the fly:<br />
<br />
<syntaxhighlight lang="javascript"><br />
// JavaScript:<br />
DoIt({numbers:[1,2,3]});<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
// Pascal;<br />
DoIt(new(['numbers',TJSArray._of(1,2,3)]));<br />
</syntaxhighlight><br />
<br />
= Resource strings =<br />
The pas2js transpiler can generate a JSON file (extension ''.jrs'') with all the resource strings in your program.<br />
<br />
This is a quite simple file. A JSON object exists for every unit, with each json property a resource string.<br />
<pre><br />
{<br />
"trs2" : {<br />
"ResUsed" : "This resourcestring is used",<br />
"ResUnUsed" : "This resourcestring is not used",<br />
"ImplResUsed" : "This implementation resourcestring is used"<br />
},<br />
"trs1" : {<br />
"MyString" : "The very nice string we will need to translate"<br />
}<br />
}<br />
</pre><br />
This file can be translated, and the translation file can be loaded using the '''rstranslate''' unit, part of the rtl.<br />
There are demo programs which demonstrate the use of this feature.<br />
<br />
The generating of this file is controlled by the '''-Jr''' option. It can take 3 possible arguments:<br />
# ''none'' This is the default, no file is generated.<br />
# ''unit'' one file per compiled unit will be generated. This file will contain all resource strings of the unit.<br />
# ''program'' one file is generated for the main file. This fill will contain all used resource strings for the main file and all the units it uses.<br />
<br />
If you compile a program, then the ''program'' option will generate a file with all the used resource strings in your program.<br />
<br />
The above example was generated using the command:<br />
<pre><br />
pas2js -Jrprogram trs1.pp -B<br />
</pre><br />
<br />
Note that the format is different from the format used by FPC:<br />
* Identifiers in the file are case sensitive: the names must be typed as they appear in the source file.<br />
* The strings are grouped per unit, this allows to load them fasters<br />
* The hash and bytes parts are missing, they make little sense in a Javascript context.<br />
<br />
= Debugging =<br />
The generated Javascript source code is of course visible and debuggable in the browser. <br />
<br />
Moreover, the transpiler can generate a source map, which means that you will be able to see and debug the Pascal code in the browser.<br />
(not everything will work, but many things do. This depends on the browser too.)<br />
<br />
A source map can be generated using the command-line parameter<br />
<pre><br />
-Jm<br />
</pre><br />
<br />
The easiest is to include the Pascal sources in the source map<br />
<pre><br />
-Jminclude<br />
</pre><br />
<br />
By default all source filenames are relative to .js.map. You can tell the compiler to store all file names relative to a specific local base directory:<br />
<pre><br />
-Jmbasedir=DirName<br />
</pre><br />
<br />
And you can store an URL in the map, so the browser will use URL/above-relative-file-name to get the source:<br />
<pre><br />
-Jmsourceroot=URL<br />
</pre><br />
<br />
=Porting from FPC/Delphi=<br />
<br />
See [[Porting from FPC/Delphi to pas2js|here]] for tips and traps porting code from FPC and Delphi.<br />
<br />
= Bugs =<br />
<br />
Please report bugs in the FPC bugtracker with category ''pas2js'': http://bugs.freepascal.org<br />
<br />
= Examples =<br />
<br />
*Time Tracking Application: https://www.devstructor.com/demos/pas2js-time/source.zip (sources: https://www.devstructor.com/demos/pas2js-time/source.zip)<br />
*Drawing and animation on canvas: http://ragnemalm.se/images/santa/santa.html (sources: http://ragnemalm.se/images/santa/)<br />
*WebGL: https://github.com/genericptr/Pas2JS-WebGL#pas2js-webgl<br />
*Allegro Web Game: https://lainz.github.io/AllegroPas2JS-Demo-Game/index.html (sources: https://github.com/lainz/AllegroPas2JS-Demo-Game)<br />
<br />
= Lazarus Widgetset =<br />
The ultimate goal is of course to have the LCL running in the web. Discussions on this topic are delegated to a separate page. [[pas2js_widgetsets]]<br />
<br />
= FAQ =<br />
<br />
== Why is a simple hello world program so big? ==<br />
<br />
This is mainly due to the used rtl.js. The rtl.js contains code for Pascal modules, classes, RTTI, sets, range checks, etc and is written with big WebApps in mind, not for scripts with a few lines of code.<br />
<br />
# You can use a Javascript [[pas2js minifier|minifier]] to reduce the created Javascript<br />
# You can create your own minified rtl.js by removing all functions you don't need. Eventually this will be done automatically by pas2js.<br />
<br />
[[Category:Pas2js]]<br />
<br />
== Why are asm blocks bad? ==<br />
<br />
Asm blocks are useful for things you cannot do with pas2js. But there are some downsides:<br />
pas2js does not parse the JS. Neither does it check the syntax, nor does it know what Pascal identifiers the code is referencing. That means any identifier only accessed by the asm block will be removed by the pas2js' optimizer.<br />
<br />
Therefore always try to do it in Pascal. Remember you can typecast values to JSValue, objects to TJSObject, arrays to TJSArray, strings to TJSString, etc to use almost all JS features.<br />
<br />
== Why not parse asm blocks? ==<br />
<br />
Any compiletime JS parser can only do a syntax check and parse only simple JS. But since simple JS can be better written in Pascal, it is somewhat pointless and has therefore low priority.<br />
<br />
== What about optimization X? ==<br />
<br />
See here for [[Pas2js optimizations]]</div>007https://wiki.freepascal.org/index.php?title=pas2js&diff=128285pas2js2019-11-05T13:45:22Z<p>007: /* Examples */</p>
<hr />
<div>{{Translate}}<br />
<br />
__TOC__<br />
= Pas2js : What is it ? =<br />
<br />
== Compiler ==<br />
Pas2js is an open source [[Pascal]] to [[JavaScript]] transpiler. It parses Object Pascal and emits JavaScript.<br />
The JavaScript is currently of level ECMAScript 5 and should run in any browser or in Node.js (target "nodejs").<br />
It is available in 3 forms:<br />
* as a library <br />
* as a command-line program<br />
* as a webserver<br />
<br />
It transpiles from actual Pascal source, it has no intermediate .ppu files. <br />
That means all sources must always be available.<br />
<br />
Through external class definitions, the compiler can use JavaScript classes:<br />
* All classes available in the JavaScript runtime, and in the browser are available <br/>through import units (comparable to the windows or unix units for the native compiler).<br />
* For Node.js, basic support for the nodejs runtime environment is available.<br />
* An import unit for jQuery is available (libjquery)<br />
<br />
As a non commercial open source project we are always searching for helping hands. If you want to contribute see [[Pas2js How to contribute|here]].<br />
<br />
This project is '''not''' related to a similar named project on github.<br />
<br />
== RTL ==<br />
For the generated code to work, a small JavaScript file is needed: rtl.js. It defines an object rtl.<br />
This object will start the Object Pascal code if you include a call to rtl.run() in the [[HTML]] page.<br />
<br />
<syntaxhighlight lang="html4strict"><br />
<script type="application/javascript"><br />
rtl.run()<br />
</script><br />
</syntaxhighlight><br />
pas2js can automatically include this file in the generated output, like this:<br />
<pre><br />
pas2js -Jc -Jirtl.js -Tbrowser hello.pas<br />
</pre><br />
For nodejs, the compiler will insert the call to rtl.run() automatically at the end of the generated Javascript file.<br />
<br />
There is a basic Object Pascal RTL, several units from the FPC Packages are also available<br />
* system<br />
* sysutils<br />
* Math<br />
* strutils<br />
* rtlconst<br />
* classes<br />
* contnrs<br />
* DB (yes, TDataset)<br />
* fpcunit testsuite<br />
* custapp<br />
* restconnection<br />
* js (javascript system objects)<br />
* web (browser provided objects)<br />
* libjquery (jquery is available too)<br />
* nodejs (basic node runtime environment)<br />
* typinfo<br />
* objpas<br />
* browserconsole (support writeln)<br />
* dateutils<br />
* browserapp<br />
* nodejsapp<br />
<br />
= Where to get it =<br />
The pas2js compiler and RTL are - naturally - open source and can be downloaded and used freely.<br />
<br />
== Daily Snapshots == <br />
The daily snapshot directory contains binaries for Linux (64 bit) for trunk and latest fixes branch.<br />
Other OSes (macOS, linux) will be made available as time permits<br />
<br />
The snapshots are uploaded to<br />
* ftp://ftpmaster.freepascal.org/fpc/contrib/pas2js/snapshot<br />
<br />
== Releases == <br />
The releases contain binaries for Windows (32 and 64bit), Linux (64 bit) and MacOS.<br />
<br />
The releases are uploaded to<br />
* ftp://ftpmaster.freepascal.org/fpc/contrib/pas2js<br />
Every version has a directory with the version number.<br />
A list of changes can be found on the changelog page [[Pas2JS Version Changes]]<br />
<br />
Download the latest release for your operating system and unpack it in folder of your choice. The example below uses C:\lazarus\pas2js. The release contains three folders:<br />
* bin - contains the compiler as executable (pas2js or pas2js.exe) and library and some utilities.<br />
* demo - lots of examples<br />
* packages - the Pascal units of the RTL and other packages.<br />
<br />
You can create a simple config to let the compiler find the RTL and packages.<br />
<br />
bin/pas2js.cfg<br />
<br />
<pre><br />
#<br />
# Minimal config file for pas2js compiler<br />
#<br />
# -d is the same as #DEFINE<br />
# -u is the same as #UNDEF<br />
#<br />
# Write always a nice logo ;)<br />
-l<br />
<br />
# Display Hints, Warnings and Notes<br />
-vwnh<br />
# If you don't want so much verbosity use<br />
#-vw<br />
<br />
# Allow C-operators<br />
-Sc<br />
<br />
-Fu$CfgDir\..\packages\*<br />
<br />
#IFDEF nodejs<br />
-Jirtl.js<br />
#ENDIF<br />
<br />
# end.<br />
</pre><br />
<br />
== SVN ==<br />
<br />
<syntaxhighlight lang="bash"><br />
svn co https://svn.freepascal.org/svn/projects/pas2js/trunk pas2js<br />
</syntaxhighlight><br />
<br />
You need [[FPC]] 3.0.4 or better to compile it.<br />
<br />
Change to the directory and build it with:<br />
<br />
<syntaxhighlight lang="bash"><br />
make clean all<br />
</syntaxhighlight><br />
<br />
This creates ''bin/$(TargetCPU)-$(TargetOS)/pas2js'' (Windows: pas2js.exe). For example on Linux 64bit it creates ''bin/x86_64-linux/pas2js'', while under Windows 64bit it creates ''bin\x86_64-win\pas2js.exe''.<br />
<br />
= How to use pas2js =<br />
<br />
The command-line arguments are kept mostly the same as the FPC command-line arguments.<br />
Error messages are also in the same format.<br />
<br />
The compiler needs access to all sources, and so you need to specify the path to the sources of <br />
all used units. <br />
<br />
As for the FPC compiler, a configuration file is supported, which has the same syntax as the FPC config file. Note that the snapshots and svn version already contains a default pas2js.cfg with unit search paths (-Fu) for the rtl and fcl. See here how for details about the [[pas2js.cfg]].<br />
<br />
Basically, the command is the same as any FPC command line. The only thing that is different is the target: ''-Tbrowser'' or ''-Tnodeejs''<br />
<br />
Here is the complete list of [[pas2js command line arguments|command line arguments]].<br />
<br />
== for the browser ==<br />
Consider the classical:<br />
<syntaxhighlight lang="pascal"><br />
program hello;<br />
<br />
begin<br />
Writeln('Hello, world!');<br />
end.<br />
</syntaxhighlight><br />
Yes, writeln is supported. Here is how to compile it:<br />
<br />
<pre><br />
pas2js -Jc -Jirtl.js -Tbrowser hello.pas<br />
</pre><br />
When compiled succesfully, the code can be run in the browser by opening a html file in the browser with the following content:<br />
<syntaxhighlight lang="html4strict"><br />
<html><br />
<head><br />
<meta charset="utf-8"/><br />
<script type="application/javascript" src="hello.js"></script><br />
</head><br />
<body><br />
<script type="application/javascript"><br />
rtl.run();<br />
</script><br />
</body><br />
</html><br />
</syntaxhighlight><br />
The files that are needed are:<br />
* hello.html<br />
* hello.js<br />
Whether hello.html is opened by double-clicking it in the explorer or put on a server and opened with an URL, is not relevant for the functioning.<br />
<br />
The output is visible in the browser's web developer console.<br />
By including the browserconsole unit, it will be visible in the browser page:<br />
<syntaxhighlight lang="pascal"><br />
program hello;<br />
<br />
uses browserconsole;<br />
<br />
begin<br />
Writeln('Hello, world!');<br />
end.<br />
</syntaxhighlight><br />
<br />
== for NodeJS ==<br />
<pre><br />
pas2js -Tnodejs hello.pas<br />
</pre><br />
When compiled succesfully, the code can be run in node using the following command.<br />
<pre><br />
nodejs hello.js<br />
</pre><br />
<br />
Note: on MacOS it is "node hello.js"<br />
<br />
= Supported syntax elements =<br />
<br />
A significant amount of Object Pascal syntax is supported, including RTTI.<br />
A more detailed list can be found in the [https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/utils/pas2js/docs/translation.html?view=co translation.html].file in the sources.<br />
<br />
*[[Mode_Delphi|Delphi]] and [[Mode_ObjFPC|ObjFPC]] mode<br />
*[[Program]], [[Unit]]s, namespaces<br />
*unit initialization, but not finalization<br />
*[[Var]], [[Const]], [[Type]]<br />
*string (unicodestring), char (widechar), [[Boolean]], [[Double]], [[Byte]], [[Shortint]], [[Word]], [[Smallint]], longword, [[Longint]], nativeint(int53), nativeuint(int52), currency<br />
*resourcestrings<br />
*[[Pointer]] (as a reference to a class, array, record, pointer of record, interface, but no pointer arithmetic)<br />
*[[Record]] (but no variant records), advanced records (since 1.3)<br />
*[[Function]]s, [[Procedure]]s, nested, anonymous functions (since 1.1)<br />
*function types, of object, reference to (closures)<br />
*function arguments: default, const, var, out<br />
*[[If]]-then-else<br />
*[[For]]-do<br />
*[[Repeat]]-until<br />
*[[While]]-do<br />
*[[With]]-do<br />
*try-finally<br />
*try-except<br />
*enums<br />
*sets<br />
*arrays static, dynamic, open, multi dimensionals, array of const<br />
*String like array operations: ''a:=[1,2,3]+[1,1];''<br />
*class type, visibility, virtual, override, abstract, overload, properties, class properties, class var, class const, constructor, destructor, class constructor (since 1.5)<br />
*class-of<br />
*nested classes<br />
*interfaces: CORBA, COM, delegations, method resolution, reference counting, TVirtualInterface<br />
*external classes, vars, const<br />
*class helpers, record helpers, type helpers (since 1.3)<br />
*Enumeration for..in..do<br />
*Type alias, e.g. type TTranslateString = type string;<br />
*RTTI<br />
*asm block for embedding JavaScript directly<br />
*compiler directives (e.g. $ifdef, $if, $define, $modeswitch, $R+)<br />
*compile time and run time range and overflow checking<br />
*[https://wiki.freepascal.org/pas2js_Generics generics] <br />
<br />
There are some constructs that are naturally not supported and will never be supported:<br />
*Anything involving memory pointers and pointer arithmetic.<br />
*Variant records<br />
<br />
Details about supported elements and the conversion from Pascal to JavaScript: [https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/utils/pas2js/docs/translation.html?view=co translation].<br />
<br />
= Planned language features =<br />
Basically, the idea is to get the pas2js transpiler up to the same level as FPC or Delphi. <br />
That means the following needs to be added:<br />
* Extended RTTI<br />
* Operator Overloading<br />
<br />
Needless to say, anything requiring direct memory access is not going to be supported.<br />
<br />
= Other not implemented features =<br />
<br />
*Array of interface<br />
*Enums with custom values<br />
*Finalization sections, class destructors<br />
*Futures<br />
*Global properties<br />
*Inline<br />
*Library<br />
*Objects<br />
*Pointer arithmetic<br />
*Record field interface<br />
*Resources<br />
*Variant records<br />
*Variants<br />
<br />
= Lazarus integration of pas2js =<br />
<br />
Lazarus understands the concept of external classes as used by pas2js, so code completion will work.<br />
<br />
Since Lazarus 1.9 the IDE can use pas2js.exe as a normal compiler.<br />
<br />
The integration is described here: [[lazarus pas2js integration]].<br />
It is still under construction, but deep integration with lazarus is planned.<br />
<br />
= Importing Javascript classes =<br />
<br />
To import a javascript class, one writes a normal class definition that mimics the Javascript class.<br />
It is possible to use properties. Many examples can be found in the JS, web, nodejs and libjquery units.<br />
<br />
Here is a simple example:<br />
<syntaxhighlight lang="pascal"><br />
TJSFunction = class external name 'Function'(TJSObject)<br />
private<br />
Flength: NativeInt external name 'length';<br />
Fprototyp: TJSFunction external name 'prototyp';<br />
public<br />
name: String;<br />
property prototyp: TJSFunction read Fprototyp;<br />
property length: NativeInt read Flength;<br />
function apply(thisArg: TJSObject; const ArgArray: TJSValueDynArray): JSValue; varargs;<br />
function bind(thisArg: TJSObject): JSValue; varargs;<br />
function call(thisArg: TJSObject): JSValue; varargs;<br />
end;<br />
</syntaxhighlight><br />
<br />
This declares the <code>TJSFunction</code> object : in Javascript, functions are objects. <br />
* The "<code>external name 'Function'</code>" means that you declare a Javascript class where the Javascript name of the class is 'Function'.<br />
* The <code>(TJSObject)</code> means it descends from <code>TJSObject</code> also an external class. There does not need to be an ancestor type.<br />
* Fields are declared just as in Pascal.<br />
* To declare read-only fields, a trick can be used:</b> declare the field using an <var>external name "thename"</code> modifier, and declare a read-only property with the same name.<br>(see the length declaration)<br />
* <code>Varargs</code> can be used to indicate that a function accepts any number of arguments.<br />
* <code>JSValue</code> can be used to indicate an unknown type. <br/>It is more or less equivalent to a Variant.<br />
<br />
= Create simple JS objects with the new function =<br />
<br />
Some JS-framework functions expect an JS object as parameter. Here is how to do that in Pascal using the ''new'' function from unit ''JS'':<br />
<br />
<syntaxhighlight lang="javascript"><br />
// JavaScript:<br />
DoIt({name:"Fred", id:3, size:4.3});<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
// Pascal;<br />
DoIt(new(['name','Fred', 'id',3, 'size',4.3]));<br />
</syntaxhighlight><br />
<br />
You can nest it to create sub objects:<br />
<br />
<syntaxhighlight lang="javascript"><br />
// JavaScript:<br />
DoIt({name:"Fred", size:{width:3,height:2}});<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
// Pascal;<br />
DoIt(new(['name','Fred', 'size',new(['width',3, 'height',2])]));<br />
</syntaxhighlight><br />
<br />
You can use TJSArray._of to create JS arrays on the fly:<br />
<br />
<syntaxhighlight lang="javascript"><br />
// JavaScript:<br />
DoIt({numbers:[1,2,3]});<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
// Pascal;<br />
DoIt(new(['numbers',TJSArray._of(1,2,3)]));<br />
</syntaxhighlight><br />
<br />
= Resource strings =<br />
The pas2js transpiler can generate a JSON file (extension ''.jrs'') with all the resource strings in your program.<br />
<br />
This is a quite simple file. A JSON object exists for every unit, with each json property a resource string.<br />
<pre><br />
{<br />
"trs2" : {<br />
"ResUsed" : "This resourcestring is used",<br />
"ResUnUsed" : "This resourcestring is not used",<br />
"ImplResUsed" : "This implementation resourcestring is used"<br />
},<br />
"trs1" : {<br />
"MyString" : "The very nice string we will need to translate"<br />
}<br />
}<br />
</pre><br />
This file can be translated, and the translation file can be loaded using the '''rstranslate''' unit, part of the rtl.<br />
There are demo programs which demonstrate the use of this feature.<br />
<br />
The generating of this file is controlled by the '''-Jr''' option. It can take 3 possible arguments:<br />
# ''none'' This is the default, no file is generated.<br />
# ''unit'' one file per compiled unit will be generated. This file will contain all resource strings of the unit.<br />
# ''program'' one file is generated for the main file. This fill will contain all used resource strings for the main file and all the units it uses.<br />
<br />
If you compile a program, then the ''program'' option will generate a file with all the used resource strings in your program.<br />
<br />
The above example was generated using the command:<br />
<pre><br />
pas2js -Jrprogram trs1.pp -B<br />
</pre><br />
<br />
Note that the format is different from the format used by FPC:<br />
* Identifiers in the file are case sensitive: the names must be typed as they appear in the source file.<br />
* The strings are grouped per unit, this allows to load them fasters<br />
* The hash and bytes parts are missing, they make little sense in a Javascript context.<br />
<br />
= Debugging =<br />
The generated Javascript source code is of course visible and debuggable in the browser. <br />
<br />
Moreover, the transpiler can generate a source map, which means that you will be able to see and debug the Pascal code in the browser.<br />
(not everything will work, but many things do. This depends on the browser too.)<br />
<br />
A source map can be generated using the command-line parameter<br />
<pre><br />
-Jm<br />
</pre><br />
<br />
The easiest is to include the Pascal sources in the source map<br />
<pre><br />
-Jminclude<br />
</pre><br />
<br />
By default all source filenames are relative to .js.map. You can tell the compiler to store all file names relative to a specific local base directory:<br />
<pre><br />
-Jmbasedir=DirName<br />
</pre><br />
<br />
And you can store an URL in the map, so the browser will use URL/above-relative-file-name to get the source:<br />
<pre><br />
-Jmsourceroot=URL<br />
</pre><br />
<br />
=Porting from FPC/Delphi=<br />
<br />
See [[Porting from FPC/Delphi to pas2js|here]] for tips and traps porting code from FPC and Delphi.<br />
<br />
= Bugs =<br />
<br />
Please report bugs in the FPC bugtracker with category ''pas2js'': http://bugs.freepascal.org<br />
<br />
= Examples =<br />
<br />
*Time Tracking Application: https://www.devstructor.com/demos/pas2js-time/source.zip (sources: https://www.devstructor.com/demos/pas2js-time/source.zip)<br />
*Drawing and animation on canvas: http://ragnemalm.se/images/santa/santa.html (sources: http://ragnemalm.se/images/santa/)<br />
*WebGL: https://github.com/genericptr/Pas2JS-WebGL#pas2js-webgl<br />
*Allegro Web Game: https://lainz.github.io/AllegroPas2JS-Demo-Game/index.html (sources: https://github.com/lainz/AllegroPas2JS-Demo-Game)<br />
*Allegro and Pixi Web Game: https://lainz.github.io/AllegroPas2JS-Demo-Game/anothertest/ (sources: https://github.com/lainz/AllegroPas2JS-Demo-Game/tree/master/anothertest)<br />
<br />
= Lazarus Widgetset =<br />
The ultimate goal is of course to have the LCL running in the web. Discussions on this topic are delegated to a separate page. [[pas2js_widgetsets]]<br />
<br />
= FAQ =<br />
<br />
== Why is a simple hello world program so big? ==<br />
<br />
This is mainly due to the used rtl.js. The rtl.js contains code for Pascal modules, classes, RTTI, sets, range checks, etc and is written with big WebApps in mind, not for scripts with a few lines of code.<br />
<br />
# You can use a Javascript [[pas2js minifier|minifier]] to reduce the created Javascript<br />
# You can create your own minified rtl.js by removing all functions you don't need. Eventually this will be done automatically by pas2js.<br />
<br />
[[Category:Pas2js]]<br />
<br />
== Why are asm blocks bad? ==<br />
<br />
Asm blocks are useful for things you cannot do with pas2js. But there are some downsides:<br />
pas2js does not parse the JS. Neither does it check the syntax, nor does it know what Pascal identifiers the code is referencing. That means any identifier only accessed by the asm block will be removed by the pas2js' optimizer.<br />
<br />
Therefore always try to do it in Pascal. Remember you can typecast values to JSValue, objects to TJSObject, arrays to TJSArray, strings to TJSString, etc to use almost all JS features.<br />
<br />
== Why not parse asm blocks? ==<br />
<br />
Any compiletime JS parser can only do a syntax check and parse only simple JS. But since simple JS can be better written in Pascal, it is somewhat pointless and has therefore low priority.<br />
<br />
== What about optimization X? ==<br />
<br />
See here for [[Pas2js optimizations]]</div>007https://wiki.freepascal.org/index.php?title=pas2js&diff=128284pas2js2019-11-05T13:43:37Z<p>007: /* Examples */</p>
<hr />
<div>{{Translate}}<br />
<br />
__TOC__<br />
= Pas2js : What is it ? =<br />
<br />
== Compiler ==<br />
Pas2js is an open source [[Pascal]] to [[JavaScript]] transpiler. It parses Object Pascal and emits JavaScript.<br />
The JavaScript is currently of level ECMAScript 5 and should run in any browser or in Node.js (target "nodejs").<br />
It is available in 3 forms:<br />
* as a library <br />
* as a command-line program<br />
* as a webserver<br />
<br />
It transpiles from actual Pascal source, it has no intermediate .ppu files. <br />
That means all sources must always be available.<br />
<br />
Through external class definitions, the compiler can use JavaScript classes:<br />
* All classes available in the JavaScript runtime, and in the browser are available <br/>through import units (comparable to the windows or unix units for the native compiler).<br />
* For Node.js, basic support for the nodejs runtime environment is available.<br />
* An import unit for jQuery is available (libjquery)<br />
<br />
As a non commercial open source project we are always searching for helping hands. If you want to contribute see [[Pas2js How to contribute|here]].<br />
<br />
This project is '''not''' related to a similar named project on github.<br />
<br />
== RTL ==<br />
For the generated code to work, a small JavaScript file is needed: rtl.js. It defines an object rtl.<br />
This object will start the Object Pascal code if you include a call to rtl.run() in the [[HTML]] page.<br />
<br />
<syntaxhighlight lang="html4strict"><br />
<script type="application/javascript"><br />
rtl.run()<br />
</script><br />
</syntaxhighlight><br />
pas2js can automatically include this file in the generated output, like this:<br />
<pre><br />
pas2js -Jc -Jirtl.js -Tbrowser hello.pas<br />
</pre><br />
For nodejs, the compiler will insert the call to rtl.run() automatically at the end of the generated Javascript file.<br />
<br />
There is a basic Object Pascal RTL, several units from the FPC Packages are also available<br />
* system<br />
* sysutils<br />
* Math<br />
* strutils<br />
* rtlconst<br />
* classes<br />
* contnrs<br />
* DB (yes, TDataset)<br />
* fpcunit testsuite<br />
* custapp<br />
* restconnection<br />
* js (javascript system objects)<br />
* web (browser provided objects)<br />
* libjquery (jquery is available too)<br />
* nodejs (basic node runtime environment)<br />
* typinfo<br />
* objpas<br />
* browserconsole (support writeln)<br />
* dateutils<br />
* browserapp<br />
* nodejsapp<br />
<br />
= Where to get it =<br />
The pas2js compiler and RTL are - naturally - open source and can be downloaded and used freely.<br />
<br />
== Daily Snapshots == <br />
The daily snapshot directory contains binaries for Linux (64 bit) for trunk and latest fixes branch.<br />
Other OSes (macOS, linux) will be made available as time permits<br />
<br />
The snapshots are uploaded to<br />
* ftp://ftpmaster.freepascal.org/fpc/contrib/pas2js/snapshot<br />
<br />
== Releases == <br />
The releases contain binaries for Windows (32 and 64bit), Linux (64 bit) and MacOS.<br />
<br />
The releases are uploaded to<br />
* ftp://ftpmaster.freepascal.org/fpc/contrib/pas2js<br />
Every version has a directory with the version number.<br />
A list of changes can be found on the changelog page [[Pas2JS Version Changes]]<br />
<br />
Download the latest release for your operating system and unpack it in folder of your choice. The example below uses C:\lazarus\pas2js. The release contains three folders:<br />
* bin - contains the compiler as executable (pas2js or pas2js.exe) and library and some utilities.<br />
* demo - lots of examples<br />
* packages - the Pascal units of the RTL and other packages.<br />
<br />
You can create a simple config to let the compiler find the RTL and packages.<br />
<br />
bin/pas2js.cfg<br />
<br />
<pre><br />
#<br />
# Minimal config file for pas2js compiler<br />
#<br />
# -d is the same as #DEFINE<br />
# -u is the same as #UNDEF<br />
#<br />
# Write always a nice logo ;)<br />
-l<br />
<br />
# Display Hints, Warnings and Notes<br />
-vwnh<br />
# If you don't want so much verbosity use<br />
#-vw<br />
<br />
# Allow C-operators<br />
-Sc<br />
<br />
-Fu$CfgDir\..\packages\*<br />
<br />
#IFDEF nodejs<br />
-Jirtl.js<br />
#ENDIF<br />
<br />
# end.<br />
</pre><br />
<br />
== SVN ==<br />
<br />
<syntaxhighlight lang="bash"><br />
svn co https://svn.freepascal.org/svn/projects/pas2js/trunk pas2js<br />
</syntaxhighlight><br />
<br />
You need [[FPC]] 3.0.4 or better to compile it.<br />
<br />
Change to the directory and build it with:<br />
<br />
<syntaxhighlight lang="bash"><br />
make clean all<br />
</syntaxhighlight><br />
<br />
This creates ''bin/$(TargetCPU)-$(TargetOS)/pas2js'' (Windows: pas2js.exe). For example on Linux 64bit it creates ''bin/x86_64-linux/pas2js'', while under Windows 64bit it creates ''bin\x86_64-win\pas2js.exe''.<br />
<br />
= How to use pas2js =<br />
<br />
The command-line arguments are kept mostly the same as the FPC command-line arguments.<br />
Error messages are also in the same format.<br />
<br />
The compiler needs access to all sources, and so you need to specify the path to the sources of <br />
all used units. <br />
<br />
As for the FPC compiler, a configuration file is supported, which has the same syntax as the FPC config file. Note that the snapshots and svn version already contains a default pas2js.cfg with unit search paths (-Fu) for the rtl and fcl. See here how for details about the [[pas2js.cfg]].<br />
<br />
Basically, the command is the same as any FPC command line. The only thing that is different is the target: ''-Tbrowser'' or ''-Tnodeejs''<br />
<br />
Here is the complete list of [[pas2js command line arguments|command line arguments]].<br />
<br />
== for the browser ==<br />
Consider the classical:<br />
<syntaxhighlight lang="pascal"><br />
program hello;<br />
<br />
begin<br />
Writeln('Hello, world!');<br />
end.<br />
</syntaxhighlight><br />
Yes, writeln is supported. Here is how to compile it:<br />
<br />
<pre><br />
pas2js -Jc -Jirtl.js -Tbrowser hello.pas<br />
</pre><br />
When compiled succesfully, the code can be run in the browser by opening a html file in the browser with the following content:<br />
<syntaxhighlight lang="html4strict"><br />
<html><br />
<head><br />
<meta charset="utf-8"/><br />
<script type="application/javascript" src="hello.js"></script><br />
</head><br />
<body><br />
<script type="application/javascript"><br />
rtl.run();<br />
</script><br />
</body><br />
</html><br />
</syntaxhighlight><br />
The files that are needed are:<br />
* hello.html<br />
* hello.js<br />
Whether hello.html is opened by double-clicking it in the explorer or put on a server and opened with an URL, is not relevant for the functioning.<br />
<br />
The output is visible in the browser's web developer console.<br />
By including the browserconsole unit, it will be visible in the browser page:<br />
<syntaxhighlight lang="pascal"><br />
program hello;<br />
<br />
uses browserconsole;<br />
<br />
begin<br />
Writeln('Hello, world!');<br />
end.<br />
</syntaxhighlight><br />
<br />
== for NodeJS ==<br />
<pre><br />
pas2js -Tnodejs hello.pas<br />
</pre><br />
When compiled succesfully, the code can be run in node using the following command.<br />
<pre><br />
nodejs hello.js<br />
</pre><br />
<br />
Note: on MacOS it is "node hello.js"<br />
<br />
= Supported syntax elements =<br />
<br />
A significant amount of Object Pascal syntax is supported, including RTTI.<br />
A more detailed list can be found in the [https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/utils/pas2js/docs/translation.html?view=co translation.html].file in the sources.<br />
<br />
*[[Mode_Delphi|Delphi]] and [[Mode_ObjFPC|ObjFPC]] mode<br />
*[[Program]], [[Unit]]s, namespaces<br />
*unit initialization, but not finalization<br />
*[[Var]], [[Const]], [[Type]]<br />
*string (unicodestring), char (widechar), [[Boolean]], [[Double]], [[Byte]], [[Shortint]], [[Word]], [[Smallint]], longword, [[Longint]], nativeint(int53), nativeuint(int52), currency<br />
*resourcestrings<br />
*[[Pointer]] (as a reference to a class, array, record, pointer of record, interface, but no pointer arithmetic)<br />
*[[Record]] (but no variant records), advanced records (since 1.3)<br />
*[[Function]]s, [[Procedure]]s, nested, anonymous functions (since 1.1)<br />
*function types, of object, reference to (closures)<br />
*function arguments: default, const, var, out<br />
*[[If]]-then-else<br />
*[[For]]-do<br />
*[[Repeat]]-until<br />
*[[While]]-do<br />
*[[With]]-do<br />
*try-finally<br />
*try-except<br />
*enums<br />
*sets<br />
*arrays static, dynamic, open, multi dimensionals, array of const<br />
*String like array operations: ''a:=[1,2,3]+[1,1];''<br />
*class type, visibility, virtual, override, abstract, overload, properties, class properties, class var, class const, constructor, destructor, class constructor (since 1.5)<br />
*class-of<br />
*nested classes<br />
*interfaces: CORBA, COM, delegations, method resolution, reference counting, TVirtualInterface<br />
*external classes, vars, const<br />
*class helpers, record helpers, type helpers (since 1.3)<br />
*Enumeration for..in..do<br />
*Type alias, e.g. type TTranslateString = type string;<br />
*RTTI<br />
*asm block for embedding JavaScript directly<br />
*compiler directives (e.g. $ifdef, $if, $define, $modeswitch, $R+)<br />
*compile time and run time range and overflow checking<br />
*[https://wiki.freepascal.org/pas2js_Generics generics] <br />
<br />
There are some constructs that are naturally not supported and will never be supported:<br />
*Anything involving memory pointers and pointer arithmetic.<br />
*Variant records<br />
<br />
Details about supported elements and the conversion from Pascal to JavaScript: [https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/utils/pas2js/docs/translation.html?view=co translation].<br />
<br />
= Planned language features =<br />
Basically, the idea is to get the pas2js transpiler up to the same level as FPC or Delphi. <br />
That means the following needs to be added:<br />
* Extended RTTI<br />
* Operator Overloading<br />
<br />
Needless to say, anything requiring direct memory access is not going to be supported.<br />
<br />
= Other not implemented features =<br />
<br />
*Array of interface<br />
*Enums with custom values<br />
*Finalization sections, class destructors<br />
*Futures<br />
*Global properties<br />
*Inline<br />
*Library<br />
*Objects<br />
*Pointer arithmetic<br />
*Record field interface<br />
*Resources<br />
*Variant records<br />
*Variants<br />
<br />
= Lazarus integration of pas2js =<br />
<br />
Lazarus understands the concept of external classes as used by pas2js, so code completion will work.<br />
<br />
Since Lazarus 1.9 the IDE can use pas2js.exe as a normal compiler.<br />
<br />
The integration is described here: [[lazarus pas2js integration]].<br />
It is still under construction, but deep integration with lazarus is planned.<br />
<br />
= Importing Javascript classes =<br />
<br />
To import a javascript class, one writes a normal class definition that mimics the Javascript class.<br />
It is possible to use properties. Many examples can be found in the JS, web, nodejs and libjquery units.<br />
<br />
Here is a simple example:<br />
<syntaxhighlight lang="pascal"><br />
TJSFunction = class external name 'Function'(TJSObject)<br />
private<br />
Flength: NativeInt external name 'length';<br />
Fprototyp: TJSFunction external name 'prototyp';<br />
public<br />
name: String;<br />
property prototyp: TJSFunction read Fprototyp;<br />
property length: NativeInt read Flength;<br />
function apply(thisArg: TJSObject; const ArgArray: TJSValueDynArray): JSValue; varargs;<br />
function bind(thisArg: TJSObject): JSValue; varargs;<br />
function call(thisArg: TJSObject): JSValue; varargs;<br />
end;<br />
</syntaxhighlight><br />
<br />
This declares the <code>TJSFunction</code> object : in Javascript, functions are objects. <br />
* The "<code>external name 'Function'</code>" means that you declare a Javascript class where the Javascript name of the class is 'Function'.<br />
* The <code>(TJSObject)</code> means it descends from <code>TJSObject</code> also an external class. There does not need to be an ancestor type.<br />
* Fields are declared just as in Pascal.<br />
* To declare read-only fields, a trick can be used:</b> declare the field using an <var>external name "thename"</code> modifier, and declare a read-only property with the same name.<br>(see the length declaration)<br />
* <code>Varargs</code> can be used to indicate that a function accepts any number of arguments.<br />
* <code>JSValue</code> can be used to indicate an unknown type. <br/>It is more or less equivalent to a Variant.<br />
<br />
= Create simple JS objects with the new function =<br />
<br />
Some JS-framework functions expect an JS object as parameter. Here is how to do that in Pascal using the ''new'' function from unit ''JS'':<br />
<br />
<syntaxhighlight lang="javascript"><br />
// JavaScript:<br />
DoIt({name:"Fred", id:3, size:4.3});<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
// Pascal;<br />
DoIt(new(['name','Fred', 'id',3, 'size',4.3]));<br />
</syntaxhighlight><br />
<br />
You can nest it to create sub objects:<br />
<br />
<syntaxhighlight lang="javascript"><br />
// JavaScript:<br />
DoIt({name:"Fred", size:{width:3,height:2}});<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
// Pascal;<br />
DoIt(new(['name','Fred', 'size',new(['width',3, 'height',2])]));<br />
</syntaxhighlight><br />
<br />
You can use TJSArray._of to create JS arrays on the fly:<br />
<br />
<syntaxhighlight lang="javascript"><br />
// JavaScript:<br />
DoIt({numbers:[1,2,3]});<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="pascal"><br />
// Pascal;<br />
DoIt(new(['numbers',TJSArray._of(1,2,3)]));<br />
</syntaxhighlight><br />
<br />
= Resource strings =<br />
The pas2js transpiler can generate a JSON file (extension ''.jrs'') with all the resource strings in your program.<br />
<br />
This is a quite simple file. A JSON object exists for every unit, with each json property a resource string.<br />
<pre><br />
{<br />
"trs2" : {<br />
"ResUsed" : "This resourcestring is used",<br />
"ResUnUsed" : "This resourcestring is not used",<br />
"ImplResUsed" : "This implementation resourcestring is used"<br />
},<br />
"trs1" : {<br />
"MyString" : "The very nice string we will need to translate"<br />
}<br />
}<br />
</pre><br />
This file can be translated, and the translation file can be loaded using the '''rstranslate''' unit, part of the rtl.<br />
There are demo programs which demonstrate the use of this feature.<br />
<br />
The generating of this file is controlled by the '''-Jr''' option. It can take 3 possible arguments:<br />
# ''none'' This is the default, no file is generated.<br />
# ''unit'' one file per compiled unit will be generated. This file will contain all resource strings of the unit.<br />
# ''program'' one file is generated for the main file. This fill will contain all used resource strings for the main file and all the units it uses.<br />
<br />
If you compile a program, then the ''program'' option will generate a file with all the used resource strings in your program.<br />
<br />
The above example was generated using the command:<br />
<pre><br />
pas2js -Jrprogram trs1.pp -B<br />
</pre><br />
<br />
Note that the format is different from the format used by FPC:<br />
* Identifiers in the file are case sensitive: the names must be typed as they appear in the source file.<br />
* The strings are grouped per unit, this allows to load them fasters<br />
* The hash and bytes parts are missing, they make little sense in a Javascript context.<br />
<br />
= Debugging =<br />
The generated Javascript source code is of course visible and debuggable in the browser. <br />
<br />
Moreover, the transpiler can generate a source map, which means that you will be able to see and debug the Pascal code in the browser.<br />
(not everything will work, but many things do. This depends on the browser too.)<br />
<br />
A source map can be generated using the command-line parameter<br />
<pre><br />
-Jm<br />
</pre><br />
<br />
The easiest is to include the Pascal sources in the source map<br />
<pre><br />
-Jminclude<br />
</pre><br />
<br />
By default all source filenames are relative to .js.map. You can tell the compiler to store all file names relative to a specific local base directory:<br />
<pre><br />
-Jmbasedir=DirName<br />
</pre><br />
<br />
And you can store an URL in the map, so the browser will use URL/above-relative-file-name to get the source:<br />
<pre><br />
-Jmsourceroot=URL<br />
</pre><br />
<br />
=Porting from FPC/Delphi=<br />
<br />
See [[Porting from FPC/Delphi to pas2js|here]] for tips and traps porting code from FPC and Delphi.<br />
<br />
= Bugs =<br />
<br />
Please report bugs in the FPC bugtracker with category ''pas2js'': http://bugs.freepascal.org<br />
<br />
= Examples =<br />
<br />
*Time Tracking Application: https://www.devstructor.com/demos/pas2js-time/source.zip (sources: https://www.devstructor.com/demos/pas2js-time/source.zip)<br />
*Drawing and animation on canvas: http://ragnemalm.se/images/santa/santa.html (sources: http://ragnemalm.se/images/santa/)<br />
*WebGL: https://github.com/genericptr/Pas2JS-WebGL#pas2js-webgl<br />
*Allegro Web Game: https://lainz.github.io/AllegroPas2JS-Demo-Game/index.html (sources: https://github.com/lainz/AllegroPas2JS-Demo-Game)<br />
<br />
= Lazarus Widgetset =<br />
The ultimate goal is of course to have the LCL running in the web. Discussions on this topic are delegated to a separate page. [[pas2js_widgetsets]]<br />
<br />
= FAQ =<br />
<br />
== Why is a simple hello world program so big? ==<br />
<br />
This is mainly due to the used rtl.js. The rtl.js contains code for Pascal modules, classes, RTTI, sets, range checks, etc and is written with big WebApps in mind, not for scripts with a few lines of code.<br />
<br />
# You can use a Javascript [[pas2js minifier|minifier]] to reduce the created Javascript<br />
# You can create your own minified rtl.js by removing all functions you don't need. Eventually this will be done automatically by pas2js.<br />
<br />
[[Category:Pas2js]]<br />
<br />
== Why are asm blocks bad? ==<br />
<br />
Asm blocks are useful for things you cannot do with pas2js. But there are some downsides:<br />
pas2js does not parse the JS. Neither does it check the syntax, nor does it know what Pascal identifiers the code is referencing. That means any identifier only accessed by the asm block will be removed by the pas2js' optimizer.<br />
<br />
Therefore always try to do it in Pascal. Remember you can typecast values to JSValue, objects to TJSObject, arrays to TJSArray, strings to TJSString, etc to use almost all JS features.<br />
<br />
== Why not parse asm blocks? ==<br />
<br />
Any compiletime JS parser can only do a syntax check and parse only simple JS. But since simple JS can be better written in Pascal, it is somewhat pointless and has therefore low priority.<br />
<br />
== What about optimization X? ==<br />
<br />
See here for [[Pas2js optimizations]]</div>007https://wiki.freepascal.org/index.php?title=Material_Design&diff=117626Material Design2018-05-21T13:11:43Z<p>007: /* Material Design */</p>
<hr />
<div>= Material Design =<br />
<br />
Material Design Components for Lazarus, painted with BGRABitmap. Licensed as LGPL v3. 2018 by Lainz.<br />
<br />
[https://github.com/bgrabitmap/materialdesign Download]<br />
<br />
= MDButton =<br />
<br />
This control can act as a normal button, toggle, toggle group, checkbox and radiobutton.<br />
<br />
== Getting Started ==<br />
<br />
Drop a MDButton from the Material Design component pallete. By default it has no animation and the colors of a basic Material Design button. You can set the properties you need, listed below.<br />
<br />
=== Properties ===<br />
<br />
* '''Animation''': show or not the ripple effect. Default value: false.<br />
* '''Checked''': used with any mode, it shows the button &quot;down&quot; state, and aditionally a glyph (radio button glyph or checkbox glyph). Default value: false.<br />
* '''Kind''': it allows you to select the behaviour of the control (normal, toggle, toggle group, checkbox, radiobutton and tab).<br />
* '''Style''': Normal, Hover, Active and Disabled colors for button and text.<br />
<br />
=== Kind ===<br />
<br />
You can use this button with other control functionality like checkbox and radiobutton.<br />
<br />
==== CheckBox mode ====<br />
<br />
With this mode, you can select (Checked: true), unselect, invert selection and get selected controls in a group. It's better than you group in a regular TPanel all checkbox buttons.<br />
<br />
==== RadioButton mode ====<br />
<br />
Whit this mode, you can select (Checked: true) only one button at a time. You can get the selected control with the method GetSelected explained below. It's better than you group in a regular TPanel all radio buttons.<br />
<br />
==== Toggle mode ====<br />
<br />
Like CheckBox mode, but no glyph is added.<br />
<br />
==== Toggle Group mode ====<br />
<br />
Like RadioButton mode, but no glyph is added.<br />
<br />
==== Tab mode ====<br />
<br />
You can use it like a tab button, to choose only one at a time, and has an animation when you select it.<br />
<br />
=== Methods ===<br />
<br />
These methods works when a set of MDButton are grouped (better on a Panel). Just call the method on any of the controls in the group. * '''SelectAll''': set all controls Checked property to true. Used when &quot;Kind&quot; property is toggle group or checkbox. * '''UnselectAll''': set all controls Checked property to false. Used when &quot;Kind&quot; property is toggle group or checkbox. * '''InvertSelection''': set all controls Checked property to the opposite. Used when &quot;Kind&quot; property is toggle group or checkbox. * '''GetSelected''': returns a TStringList containing the caption and the MDButton (Objects) that has the property Checked set to true.<br />
<br />
=== Globals ===<br />
<br />
<ul><br />
<li><p>'''Animate only one button at a time''': with this define, you can limit the number of animations being played at the same time in the whole application for all MDButton controls. Enabled by default.</p><br />
<source lang="pascal">{$DEFINE MDBUTTON_ANIMATEONLYONE} </source></li><br />
<li><p>'''CheckBox and RadioButton glyphs''': you can change in the source of MDButton or by code the next global variables. Notice that the font you use must have these glyphs in each target OS. Modern OS should already have them.</p><br />
<source lang="pascal">var<br />
MDBUTTONBALLOTBOX: string = '✗';<br />
MDBUTTONBALLOTBOXWITHCHECK: string = '✓';<br />
MDBUTTONRADIOBUTTON: string = '🔘';<br />
MDBUTTONRADIOBUTTONCIRCLE: string = '◯';</source></li></ul></div>007https://wiki.freepascal.org/index.php?title=Material_Design&diff=117625Material Design2018-05-21T13:10:57Z<p>007: </p>
<hr />
<div>= Material Design =<br />
<br />
Material Design Components for Lazarus, painted with BGRABitmap. Licensed as LGPL v3. 2018 by Lainz.<br />
<br />
= MDButton =<br />
<br />
This control can act as a normal button, toggle, toggle group, checkbox and radiobutton.<br />
<br />
== Getting Started ==<br />
<br />
Drop a MDButton from the Material Design component pallete. By default it has no animation and the colors of a basic Material Design button. You can set the properties you need, listed below.<br />
<br />
=== Properties ===<br />
<br />
* '''Animation''': show or not the ripple effect. Default value: false.<br />
* '''Checked''': used with any mode, it shows the button &quot;down&quot; state, and aditionally a glyph (radio button glyph or checkbox glyph). Default value: false.<br />
* '''Kind''': it allows you to select the behaviour of the control (normal, toggle, toggle group, checkbox, radiobutton and tab).<br />
* '''Style''': Normal, Hover, Active and Disabled colors for button and text.<br />
<br />
=== Kind ===<br />
<br />
You can use this button with other control functionality like checkbox and radiobutton.<br />
<br />
==== CheckBox mode ====<br />
<br />
With this mode, you can select (Checked: true), unselect, invert selection and get selected controls in a group. It's better than you group in a regular TPanel all checkbox buttons.<br />
<br />
==== RadioButton mode ====<br />
<br />
Whit this mode, you can select (Checked: true) only one button at a time. You can get the selected control with the method GetSelected explained below. It's better than you group in a regular TPanel all radio buttons.<br />
<br />
==== Toggle mode ====<br />
<br />
Like CheckBox mode, but no glyph is added.<br />
<br />
==== Toggle Group mode ====<br />
<br />
Like RadioButton mode, but no glyph is added.<br />
<br />
==== Tab mode ====<br />
<br />
You can use it like a tab button, to choose only one at a time, and has an animation when you select it.<br />
<br />
=== Methods ===<br />
<br />
These methods works when a set of MDButton are grouped (better on a Panel). Just call the method on any of the controls in the group. * '''SelectAll''': set all controls Checked property to true. Used when &quot;Kind&quot; property is toggle group or checkbox. * '''UnselectAll''': set all controls Checked property to false. Used when &quot;Kind&quot; property is toggle group or checkbox. * '''InvertSelection''': set all controls Checked property to the opposite. Used when &quot;Kind&quot; property is toggle group or checkbox. * '''GetSelected''': returns a TStringList containing the caption and the MDButton (Objects) that has the property Checked set to true.<br />
<br />
=== Globals ===<br />
<br />
<ul><br />
<li><p>'''Animate only one button at a time''': with this define, you can limit the number of animations being played at the same time in the whole application for all MDButton controls. Enabled by default.</p><br />
<source lang="pascal">{$DEFINE MDBUTTON_ANIMATEONLYONE} </source></li><br />
<li><p>'''CheckBox and RadioButton glyphs''': you can change in the source of MDButton or by code the next global variables. Notice that the font you use must have these glyphs in each target OS. Modern OS should already have them.</p><br />
<source lang="pascal">var<br />
MDBUTTONBALLOTBOX: string = '✗';<br />
MDBUTTONBALLOTBOXWITHCHECK: string = '✓';<br />
MDBUTTONRADIOBUTTON: string = '🔘';<br />
MDBUTTONRADIOBUTTONCIRCLE: string = '◯';</source></li></ul></div>007https://wiki.freepascal.org/index.php?title=Material_Design&diff=117624Material Design2018-05-21T13:10:26Z<p>007: Created page with "# Material Design Material Design Components for Lazarus, painted with BGRABitmap. Licensed as LGPL v3. 2018 by Lainz. # MDButton This control can act as a normal button, t..."</p>
<hr />
<div># Material Design<br />
Material Design Components for Lazarus, painted with BGRABitmap. Licensed as LGPL v3. 2018 by Lainz.<br />
<br />
<br />
<br />
# MDButton<br />
This control can act as a normal button, toggle, toggle group, checkbox and radiobutton.<br />
<br />
## Getting Started<br />
Drop a MDButton from the Material Design component pallete. By default it has no animation and the colors of a basic Material Design button. You can set the properties you need, listed below.<br />
<br />
### Properties<br />
* **Animation**: show or not the ripple effect. Default value: false.<br />
* **Checked**: used with any mode, it shows the button "down" state, and aditionally a glyph (radio button glyph or checkbox glyph). Default value: false.<br />
* **Kind**: it allows you to select the behaviour of the control (normal, toggle, toggle group, checkbox, radiobutton and tab).<br />
* **Style**: Normal, Hover, Active and Disabled colors for button and text.<br />
<br />
### Kind<br />
You can use this button with other control functionality like checkbox and radiobutton.<br />
<br />
#### CheckBox mode<br />
With this mode, you can select (Checked: true), unselect, invert selection and get selected controls in a group. It's better than you group in a regular TPanel all checkbox buttons.<br />
<br />
#### RadioButton mode<br />
Whit this mode, you can select (Checked: true) only one button at a time. You can get the selected control with the method GetSelected explained below. It's better than you group in a regular TPanel all radio buttons.<br />
<br />
#### Toggle mode<br />
Like CheckBox mode, but no glyph is added.<br />
<br />
#### Toggle Group mode<br />
Like RadioButton mode, but no glyph is added.<br />
<br />
#### Tab mode<br />
You can use it like a tab button, to choose only one at a time, and has an animation when you select it.<br />
<br />
### Methods<br />
These methods works when a set of MDButton are grouped (better on a Panel). Just call the method on any of the controls in the group.<br />
* **SelectAll**: set all controls Checked property to true. Used when "Kind" property is toggle group or checkbox.<br />
* **UnselectAll**: set all controls Checked property to false. Used when "Kind" property is toggle group or checkbox.<br />
* **InvertSelection**: set all controls Checked property to the opposite. Used when "Kind" property is toggle group or checkbox.<br />
* **GetSelected**: returns a TStringList containing the caption and the MDButton (Objects) that has the property Checked set to true.<br />
<br />
### Globals<br />
* **Animate only one button at a time**: with this define, you can limit the number of animations being played at the same time in the whole application for all MDButton controls. Enabled by default.<br />
```pascal<br />
{$DEFINE MDBUTTON_ANIMATEONLYONE} <br />
```<br />
* **CheckBox and RadioButton glyphs**: you can change in the source of MDButton or by code the next global variables. Notice that the font you use must have these glyphs in each target OS. Modern OS should already have them.<br />
```pascal<br />
var<br />
MDBUTTONBALLOTBOX: string = '✗';<br />
MDBUTTONBALLOTBOXWITHCHECK: string = '✓';<br />
MDBUTTONRADIOBUTTON: string = '🔘';<br />
MDBUTTONRADIOBUTTONCIRCLE: string = '◯';</div>007https://wiki.freepascal.org/index.php?title=BGRABitmap&diff=117623BGRABitmap2018-05-21T13:08:46Z<p>007: /* Additional packages */</p>
<hr />
<div>{{BGRABitmap}}<br />
<br />
See also: [[Developing with Graphics]]<br />
<br />
===Description===<br />
'''BGRABitmap''' is a set of units designed to modify and create images with transparency (alpha channel). Direct pixel access allows fast image processing. The library has been tested on Windows, Ubuntu and Mac OS X (The last version doesn't work on Mac), with widgetsets win32, gtk1, gtk2 and carbon.<br />
<br />
The main class is [[TBGRABitmap class|TBGRABitmap]], which is derived from [[fcl-image|TFPCustomImage]]. There is also [[TBGRAPtrBitmap class|TBGRAPtrBitmap]] which allows to edit BGRA data that are already allocated. This format consists of 4 bytes for each pixel (blue, green, red and alpha in that order).<br />
<br />
The image can be rendered on a regular Canvas or on an [[BGRABitmap and OpenGL|OpenGL surface]].<br />
<br />
===Additional packages===<br />
Some package use BGRABitmap to provide controls with nice graphics:<br />
*BGLControls: provides TBGLVirtualScreen to draw on an OpenGL surface. This package is in BGRABitmap archive.<br />
*[[BGRAControls]]: lablels wth shadows, beautiful buttons, shapes, etc.<br />
*[[uE Controls]]: gauges, LEDs, etc.<br />
*[[Material Design]]: Google material design guidelines based UI components.<br />
*BGRAControlsFX[https://forum.lazarus.freepascal.org/index.php?topic=34534.0]: controls rendering on OpenGL surface<br />
<br />
Some examples in the test folder use BGRAControls and BGLControls. You may need to install them to open these projects within Lazarus. See [[Install Packages]].<br />
<br />
===Using BGRABitmap===<br />
<br />
====Tutorial====<br />
<br />
*[http://www.youtube.com/watch?v=HGYSLgtYx-U How to convert an application from TCanvas to BGRABitmap]<br />
*[[BGRABitmap tutorial TAChart|Using BGRABitmap to render a TAChart]]<br />
*[[BGRABitmap tutorial|A series of tutorials to learn step by step]]<br />
*Examples in [https://github.com/bgrabitmap GitHub].<br />
<br />
====Overview====<br />
<br />
Functions have long names in order to be understandable. Almost everything is accessible as a function or using a property of the [[TBGRABitmap class|TBGRABitmap]] object. For example, you can use CanvasBGRA to have some canvas similar to TCanvas (with opacity and antialiasing) and Canvas2D to have the same features as the [https://developer.mozilla.org/en/HTML:Canvas HTML canvas].<br />
<br />
Some special features require the use of units, but you may not need them :<br />
* TBGRAMultishapeFiller to have an antialiased junctions of polygons is in BGRAPolygon<br />
* TBGRATextEffect is in BGRATextFX<br />
* 2D transformations are in BGRATransform<br />
* TBGRAScene3D is in BGRAScene3D<br />
* If you need to have layers, BGRALayers provides TBGRALayeredBitmap<br />
<br />
Double-buffering is not really part of BGRABitmap, because it is more about how to handle forms. To do double-buffering, you can use TBGRAVirtualScreen which is in the [[BGRAControls]] package. Apart from that, double-buffering in BGRABitmap works like any double-buffering. You need to have a bitmap where you store your drawing and that you display with a single Draw instruction.<br />
<br />
====BGRABitmapTypes unit reference====<br />
<br />
* [[BGRABitmap Pixel types|Pixel types and functions]]: ''TBGRAPixel'', ''THSLAPixel''...<br />
* [[BGRABitmap Types imported from Graphics|Types imported from Graphics]]: ''TColor'', pen style...<br />
* [[BGRABitmap Color definitions|Color definitions]]: ''VGAColors'', ''CSSColors''...<br />
* [[BGRABitmap Geometry types|Geometry types]]: ''TPointF'', Bezier curves, ''TArcDef''...<br />
* [[BGRABitmap Miscellaneous types|Miscellaneous types]]: font, image format, resampling...<br />
* [[TBGRACustomBitmap and IBGRAScanner]]: the base class for ''TBGRABitmap'' and scanners<br />
<br />
==== Installation ====<br />
After unpacking a checkout, BGRA often does not compile in Linux. Try using the IDE Macro <br />
<br />
LCLWidgetType:=gtk2<br />
<br />
in such cases. Still some other part may not compile.<br />
<br />
====Simple example====<br />
<br />
Create a project and open bgrabitmappackage.lpk with Lazarus. In the package window, click on "Use > Add to Project". Then in the source code of the main file (main form or main program), add to uses clause BGRABitmap units. You may need to add BGRAGraphics unit as well if you use certain types that are inherited from the LCL.<br />
<syntaxhighlight><br />
Uses Classes, SysUtils, BGRABitmap, BGRABitmapTypes;<br />
</syntaxhighlight><br />
<br />
The unit BGRABitmapTypes contains common definitions, but one can declare only BGRABitmap in order to load and show a bitmap. Then, the first step is to create a [[TBGRABitmap class|TBGRABitmap]] object:<br />
<syntaxhighlight><br />
var bmp: TBGRABitmap;<br />
begin<br />
bmp := TBGRABitmap.Create(100,100,BGRABlack); //creates a 100x100 pixels image with black background<br />
<br />
bmp.FillRect(20,20,60,60,BGRAWhite, dmSet); //draws a white square without transparency<br />
bmp.FillRect(40,40,80,80,BGRA(0,0,255,128), dmDrawWithTransparency); //draws a transparent blue square<br />
...<br />
end;<br />
</syntaxhighlight><br />
<br />
Finally to show the bitmap:<br />
<syntaxhighlight><br />
procedure TFMain.FormPaint(Sender: TObject);<br />
begin<br />
bmp.Draw(Canvas, 0, 0, True); // draw the bitmap in opaque mode (faster)<br />
end;<br />
</syntaxhighlight><br />
<br />
See a full source code in [[BGRABitmap tutorial 1|tutorial 1]].<br />
<br />
===Notions===<br />
<br />
Pixels in a bitmap with transparency are stored with 4 values, here 4 bytes in the order Blue, Green, Red, Alpha. The last channel defines the level of opacity (0 signifies transparent, 255 signifies opaque), other channels define color and luminosity.<br />
<br />
There are basically two drawing modes. The first consists in replacing the content of the pixel information, the second consists in blending the pixel already here with the new one, which is called alpha blending.<br />
<br />
BGRABitmap functions propose 4 modes:<br />
* dmSet : replaces the four bytes of the drawn pixel, transparency not handled<br />
* dmDrawWithTransparency : draws with alphablending and with gamma correction (see below)<br />
* dmFastBlend or dmLinearBlend : draws with alphablending but without gamma correction (faster but entails color distortions with low intensities).<br />
* dmXor : apply Xor to each component including alpha (if you want to invert color but keep alpha, use BGRA(255,255,255,0) )<br />
<br />
===Integrated drawing functions===<br />
<br />
* draw/erase pixels<br />
* draw a line with or without antialiasing<br />
* floating point coordinates<br />
* floating point pen width<br />
* rectangle (frame or fill)<br />
* ellipse and polygons with antialiasing<br />
* spline computation (rounded curve)<br />
* simple fill (Floodfill) or progressive fill<br />
* color gradient rendering (linear, radial...)<br />
* round rectangles<br />
* texts with transparency<br />
<br />
===Drawing with the Canvas===<br />
<br />
It is possible to draw with a ''Canvas'' object, with usual functions but without antialiasing. Opacity of drawing is defined by the ''CanvasOpacity'' property. This way is slower because it needs image transformations. If you can, use CanvasBGRA instead, which allows transparency and antialiasing while having the same function names as with TCanvas.<br />
<br />
===Direct access to pixels===<br />
<br />
To access pixels, there are two properties, ''Data'' and ''Scanline''. The first gives a pointer to the first pixel of the image, and the second gives a pointer to the first pixel of a given line.<br />
<br />
<syntaxhighlight><br />
var <br />
bmp: TBGRABitmap;<br />
p: PBGRAPixel;<br />
n: integer;<br />
<br />
begin<br />
bmp := TBGRABitmap.Create('image.png');<br />
p := bmp.Data;<br />
for n := bmp.NbPixels-1 downto 0 do<br />
begin<br />
p^.red := not p^.red; //invert red channel<br />
inc(p);<br />
end;<br />
bmp.InvalidateBitmap; //note that we have accessed pixels directly<br />
bmp.Draw(Canvas,0,0,True);<br />
bmp.Free;<br />
end;<br />
</syntaxhighlight><br />
<br />
It is necessary to call the function ''InvalidateBitmap'' to rebuild the image in a next call to ''Draw''' for example. Notice that the line order can be reverse, depending on the ''LineOrder'' property.<br />
<br />
See also the comparison between [[Fast direct pixel access|direct pixel access methods]].<br />
<br />
=== Image manipulation ===<br />
<br />
Available filters (prefixed with Filter) :<br />
<br />
* Radial blur : non directional blur<br />
* Motion blur : directional blur<br />
* Custom blur : blur according to a mask<br />
<br />
* Median : computes the median of colors around each pixel, which softens corners<br />
* Pixelate : simplifies the image with rectangles of the same color<br />
* Smooth : soften whole image, complementary to Sharpen<br />
* Sharpen : makes contours more accute, complementary to Smooth<br />
<br />
* Contour : draws contours on a white background (like a pencil drawing)<br />
* Emboss : draws contours with shadow<br />
* EmbossHighlight : draws contours of a selection defined with grayscale<br />
<br />
* Grayscale : converts colors to grayscale with gamma correction<br />
* Normalize : uses whole range of color luminosity <br />
<br />
* Rotate : rotation of the image around a point<br />
* Sphere : distorts the image to make it look like projected on a sphere<br />
* Twirl : distorts the image with a twirl effect<br />
* Cylinder : distorts the image to make it look like projected on a cylinder<br />
* Plane : computes a high precision projection on a horizontal plane. This is quite slow.<br />
* SmartZoom3 : resizes the image x3 and detects borders, to have a useful zoom with ancient games sprites<br />
<br />
Some functions are not prefixed with Filter, because they do not return a newly allocated image. They modify the image in-place :<br />
* VerticalFlip : flips the image vertically<br />
* HorizontalFlip : flips the image horizontally<br />
* Negative : inverse of colors<br />
* LinearNegative : inverse without gamma correction<br />
* SwapRedBlue : swap red and blue channels (to convert between BGRA and RGBA)<br />
* ConvertToLinearRGB : to convert from sRGB to RGB. Note the format used by BGRABitmap is sRGB when using<br />
dmDrawWithTransparency and RGB when using dmLinearBlend.<br />
* ConvertFromLinearRGB : convert from RGB to sRGB.<br />
<br />
=== Images combination ===<br />
<br />
PutImage is the basic image drawing function and BlendImage allows to combine images, like layers of image editing softwares. Available modes are the following:<br />
*LinearBlend : simple superimposition without gamma correction (equivalent to dmFastBlend)<br />
*Transparent : superimposition with gamma correction<br />
*Multiply : multiplication of color values (with gamma correction)<br />
*LinearMultiply : multiplication of color values (without gamma correction)<br />
*Additive : addition of color values (with gamma correction)<br />
*LinearAdd : addition of color values (without gamma correction)<br />
*Difference : difference of color values (with gamma correction)<br />
*LinearDifference : difference of color values (without gamma correction)<br />
*Negation : makes common colors disappear (with gamma correction)<br />
*LinearNegation : makes common colors disappear (without gamma correction)<br />
*Reflect, Glow : for light effects<br />
*ColorBurn, ColorDodge, Overlay, Screen : misc. filters<br />
*Lighten : keeps the lightest color values<br />
*Darken : keeps the darkest color values<br />
*Xor : exclusive or of color values<br />
<br />
These modes can be used in TBGRALayeredBitmap, which makes it easier because BlendImage only provides the basic blending operations.<br />
<br />
=== Screenshots ===<br />
[[Image:Lazpaint_contour.png]]<br />
[[Image:Lazpaint curve redim.png]]<br />
[[Image:Bgra_wirecube.png]]<br />
[[Image:Bgra_chessboard.jpg]]<br />
<br />
===Licence===<br />
modified LGPL<br />
<br />
Author: [http://johann-elsass.net Johann ELSASS] ([http://www.facebook.com/johann.elsass.1 Facebook])<br />
<br />
===Download===<br />
Latest version: https://github.com/bgrabitmap/bgrabitmap/releases<br />
<br />
Sourceforge with [[LazPaint|LazPaint]]: http://sourceforge.net/projects/lazpaint/files/src/<br />
<br />
GitHub: https://github.com/bgrabitmap/<br />
<br />
Old link : http://lazarus.johann-elsass.net/<br />
<br />
[[Category:Components]]<br />
[[Category:Graphics]]<br />
[[Category: BGRABitmap]]</div>007https://wiki.freepascal.org/index.php?title=BGRAControls&diff=114249BGRAControls2017-12-13T21:47:09Z<p>007: /* Install */</p>
<hr />
<div>{{BGRAControls}}<br />
<br />
= Install =<br />
<br />
Use the [[Online Package Manager]] to get BGRABitmap and BGRAControls.<br />
<br />
Notice that you must check only the packages "bgrabitmappack.lpk" and "bgracontrols.lpk" in the Online Package Manager. The other packages are optional and may need third party packages / libraries to work (OpenGL and PascalScript).<br />
<br />
== Optional Components ==<br />
<br />
Since v4.4 the components TBCDefaultThemeManager, TBCKeyboard and TBCNumericKeyboard are not installed by default to allow Linux users to get a seamless installation with the Online Package Manager not installing third party stuff. If you want these components turn on the "Register unit" in the package options for each file (bcdefaulthememanager.pas, bckeyboard.pas, bcnumerickeyboard.pas) then compile and rebuild Lazarus. On Linux you need to install libxtst-dev and libgl-dev first.<br />
<br />
== Website ==<br />
<br />
BGRABitmap Organization on GitHub: https://github.com/bgrabitmap/<br />
<br />
= BGRA Controls =<br />
<br />
BGRA Controls is a set of graphical UI elements that you can use with Lazarus LCL applications.<br />
Under Linux you need to have installed libxtst-dev and libgl-dev.<br />
<br />
=== TBCButton ===<br />
<br />
[[Image:bcbutton.png]]<br />
<br />
A button control that can be styled through properties for each state like StateClicked, StateHover, StateNormal with settings like gradients, border and text with shadows. You can assign an already made style through the property AssignStyle.<br />
<br />
=== TBCButtonFocus ===<br />
<br />
Like TBCButton but it supports focus like normal TButton.<br />
<br />
=== TBCGameGrid ===<br />
<br />
[[Image:bcgamegrid.png]]<br />
<br />
A grid with custom width and height of items and any number of horizontal and vertical cells that can be drawn with BGRABitmap directly with the OnRenderControl event.<br />
<br />
=== TBCImageButton ===<br />
<br />
[[Image:samplebgraimagebutton.png]]<br />
<br />
[[Image:samplebgraimagebuttonalpha.png]]<br />
<br />
A button control that can be styled with one image file, containing the drawing for each state Normal, Hovered, Active and Disabled. It supports 9-slice scaling feature. It supports a nice fading animation that can be turned on.<br />
<br />
=== TBCXButton ===<br />
<br />
[[Image:bcxbutton.png]]<br />
<br />
A button control that can be styled by code with the OnRenderControl event. Or even better create your own child control inheriting from this class.<br />
<br />
=== TBCLabel ===<br />
<br />
[[Image:bclabel.png]]<br />
<br />
A label control that can be styled through properties, it supports shadow, custom borders and background.<br />
<br />
=== TBCMaterialDesignButton ===<br />
<br />
A button control that has an animation effect according to Google Material Design guidelines. It supports custom color for background and for the circle animation, also you can customize the shadow.<br />
<br />
=== TBCPanel ===<br />
<br />
[[Image:bcpanel.png]]<br />
<br />
A panel control that can be styled through properties. You can assign an already made style through the property AssignStyle.<br />
<br />
=== TBCRadialProgressBar ===<br />
<br />
A progress bar with radial style. You can set the color and text properties as you like.<br />
<br />
=== TBCToolBar ===<br />
<br />
A TToolBar with an event OnRedraw to paint it using BGRABitmap. It supports also the default OnPaintButton to customize the buttons drawing. By default it comes with a Windows 7 like explorer toolbar style.<br />
<br />
=== TBCTrackBarUpdown ===<br />
<br />
A control to input numeric values with works like a trackbar and a spinedit both in one control.<br />
<br />
=== TBGRAFlashProgressBar ===<br />
<br />
[[Image:BC-Bgraflashprogressbar.png]]<br />
<br />
A progress bar with a default style inspired in the old Flash Player Setup for Windows progress dialog. You can change the color property to have different styles and also you can use the event OnRedraw to paint custom styles on it like text or override the entire default drawing.<br />
<br />
=== TBGRAGraphicControl ===<br />
<br />
Is like a paintbox. You can draw with transparency with this control using the OnRedraw event.<br />
<br />
=== TBGRAImageList ===<br />
<br />
[[Image:before-TImageList.png]]<br />
<br />
[[Image:after-TBGRAImageList.png]]<br />
<br />
An image list that supports alpha in all supported platforms.<br />
<br />
=== TBGRAImageManipulation ===<br />
<br />
[[Image:bgraimagemanipulation.jpg]]<br />
<br />
A tool to manipulate pictures, see the demo that shows all the capability that comes with it.<br />
<br />
=== TBGRAKnob ===<br />
<br />
[[Image:BC-Bgraknob.png]]<br />
<br />
A knob that can be styled through properties.<br />
<br />
=== TBGRAResizeSpeedButton ===<br />
<br />
A speed button that can resize the glyph to fit in the entire control.<br />
<br />
=== TBGRAShape ===<br />
<br />
[[Image:samplebgrashape.png]]<br />
<br />
A control with configurable shapes like polygon and ellipse that can be filled with gradients and can have custom borders and many other visual settings.<br />
<br />
=== TBGRASpeedButton ===<br />
<br />
[[Image:BGRASpeedButton.png]]<br />
<br />
A speed button that in GTK and GTK2 provides BGRABitmap powered transparency to the glyph.<br />
<br />
=== TBGRASpriteAnimation ===<br />
<br />
[[Image:bgraspriteanimation.png]]<br />
<br />
A component that can be used as image viewer or animation viewer, supports the loading of gif files.<br />
<br />
=== TBGRAVirtualScreen ===<br />
<br />
Is like a panel. You can draw this control using the OnRedraw event.<br />
<br />
=== TDTAnalogClock ===<br />
<br />
A clock.<br />
<br />
=== TDTAnalogGaugue ===<br />
<br />
A gauge.<br />
<br />
=== TDTThemedClock ===<br />
<br />
Another clock.<br />
<br />
=== TDTThemedGauge ===<br />
<br />
Another gauge.<br />
<br />
=== TPSImport_BGRAPascalScript ===<br />
<br />
A component to load BGRABitmap pascal script utilities.<br />
<br />
= BGRA Custom Drawn =<br />
<br />
BGRA Custom Drawn is a set of controls inherited from Custom Drawn. These come with a default dark style that is like Photoshop.<br />
<br />
=== TBCDButton ===<br />
<br />
A button control that is styled with TBGRADrawer.<br />
<br />
=== TBCDEdit ===<br />
<br />
An edit control that is styled with TBGRADrawer.<br />
<br />
=== TBCDStaticText ===<br />
<br />
A label control that is styled with TBGRADrawer.<br />
<br />
=== TBCDProgressBar ===<br />
<br />
A progress bar control that is styled with TBGRADrawer.<br />
<br />
=== TBCDSpinEdit ===<br />
<br />
A spin edit control that is styled with TBGRADrawer.<br />
<br />
=== TBCDCheckBox ===<br />
<br />
A check box control that is styled with TBGRADrawer.<br />
<br />
=== TBCRadioButton ===<br />
<br />
A radio button that is styled with TBGRADrawer.<br />
<br />
= Sample code =<br />
<br />
BGRA Controls comes with nice demos to show how to use the stuff and extra things you can use in your own projects.<br />
<br />
=== Pascal Script Library ===<br />
<br />
Putting BGRABitmap methods into a .dll with c#, java and pascal headers.<br />
<br />
=== BGRA Ribbon Custom ===<br />
<br />
How to create a fully themed window using the controls to achieve a Ribbon like application.<br />
<br />
=== Tests ===<br />
<br />
There are test for analog controls (clock and gauge), BC prefixed controls, BGRA prefixed controls, BGRA Custom Drawn controls, how to use Pascal Script and BGRABitmap, bgrascript or how to create your own scripting solution with BGRABitmap.<br />
<br />
=== Tests Extra ===<br />
<br />
[[Image:game_maze.png]]<br />
<br />
[[Image:game_puzzle.png]]<br />
<br />
[[Image:customdrawnwindows7.png]]<br />
<br />
[[File:slicescaledtachart.png]]<br />
<br />
These are extra tests like how to use fading effect, an fpGUI theme, games like maze and puzzle, how we created the material design animation, pix2svg or how to convert a small picture to svg using hexagons, rectangles and ellipses, plugins or how to load .dlls and use into a TBGRAVirtualScreen, rain effect, shadow effect, 9-slice-scaling with Custom Drawn or how to theme with bitmaps an application to look like Windows themes and 9-slice-scaling with charts.<br />
<br />
= Another units =<br />
<br />
These units come with BGRA Controls and contains more functionality that is sometimes used with the controls, sometimes not but are usefull in some way. Some are listed here, others you can see linked directly with any control like bcrtti, bcstylesform, bctools and bctypes.<br />
<br />
=== BCEffect ===<br />
<br />
Fading effect with BGRABitmap.<br />
<br />
=== BCFilters ===<br />
<br />
A set of pixel filters to use with BGRABitmap.<br />
<br />
=== BGRAScript ===<br />
<br />
Scripting with BGRABitmap, see test project.<br />
<br />
= Related Articles =<br />
<br />
[[BGRASpriteAnimation]] - Usage of the sprite animation component.<br />
<br />
[[uE_Controls]] - Other controls developed with BGRABitmap.<br />
<br />
[[BGRABitmap]] - The library used to create this controls.<br />
<br />
[[LazPaint]] - A paint program developed with Lazarus and BGRABitmap.<br />
<br />
[[Category:Components]]<br />
[[Category:Graphics]]<br />
[[Category:BGRAControls]]</div>007https://wiki.freepascal.org/index.php?title=Lazarus-ccr_GitHub_organization&diff=113949Lazarus-ccr GitHub organization2017-11-24T23:45:15Z<p>007: /* Hosted Projects */</p>
<hr />
<div>== Introduction ==<br />
<br />
There's a [https://github.com/lazarusccr Lazarus Code and Component Repository organization at GitHub]. If you want to host a repository there you need to contact one of the administrators: JuhaManninen or GetMem, all of them can be contacted in the Lazarus forum.<br />
<br />
Each repository can have one or multiple people working on it. When access as member of the organization is given to you, you can create as many repositories you need, and in the settings add one or more collaborators.<br />
<br />
== Members ==<br />
<br />
Actually the administrators are:<br />
<br />
# GetMem<br />
# JuhaManninen<br />
<br />
Actually the members are:<br />
<br />
# minesadorada<br />
<br />
== Hosted Projects ==<br />
<br />
Currently we have:<br />
<br />
# GraphicsContest: The yearly Lazarus forum Graphics Contest repository.<br />
# LazarusPackagesRepository: Sources of the web version of the Lazarus Packages Repository<br />
# TestApp: Temporary testing repository for LazAutoUpdate<br />
# apps: Showcase of Lazarus Applications</div>007https://wiki.freepascal.org/index.php?title=Lazarus-ccr_GitHub_organization&diff=113948Lazarus-ccr GitHub organization2017-11-24T23:43:53Z<p>007: /* Introduction */</p>
<hr />
<div>== Introduction ==<br />
<br />
There's a [https://github.com/lazarusccr Lazarus Code and Component Repository organization at GitHub]. If you want to host a repository there you need to contact one of the administrators: JuhaManninen or GetMem, all of them can be contacted in the Lazarus forum.<br />
<br />
Each repository can have one or multiple people working on it. When access as member of the organization is given to you, you can create as many repositories you need, and in the settings add one or more collaborators.<br />
<br />
== Members ==<br />
<br />
Actually the administrators are:<br />
<br />
# GetMem<br />
# JuhaManninen<br />
<br />
Actually the members are:<br />
<br />
# minesadorada<br />
<br />
== Hosted Projects ==<br />
<br />
Currently we have:<br />
<br />
# GraphicsContest (lainz): The yearly Lazarus forum Graphics Contest repository.<br />
<br />
And many test projects.</div>007https://wiki.freepascal.org/index.php?title=Lazarus-ccr_GitHub_organization&diff=113947Lazarus-ccr GitHub organization2017-11-24T23:43:37Z<p>007: /* Members */</p>
<hr />
<div>== Introduction ==<br />
<br />
There's a [https://github.com/lazarusccr Lazarus Code and Component Repository organization at GitHub]. If you want to host a repository there you need to contact one of the administrators: lainz, JuhaManninen or GetMem, all of them can be contacted in the Lazarus forum.<br />
<br />
Each repository can have one or multiple people working on it. When access as member of the organization is given to you, you can create as many repositories you need, and in the settings add one or more collaborators.<br />
<br />
== Members ==<br />
<br />
Actually the administrators are:<br />
<br />
# GetMem<br />
# JuhaManninen<br />
<br />
Actually the members are:<br />
<br />
# minesadorada<br />
<br />
== Hosted Projects ==<br />
<br />
Currently we have:<br />
<br />
# GraphicsContest (lainz): The yearly Lazarus forum Graphics Contest repository.<br />
<br />
And many test projects.</div>007https://wiki.freepascal.org/index.php?title=Projects_using_Free_Pascal&diff=111634Projects using Free Pascal2017-08-23T17:09:33Z<p>007: /* See also */</p>
<hr />
<div>{{Projects using Lazarus}}<br />
<br />
==See also==<br />
<br />
* [[Lazarus Application Gallery]] <br />
* [[Components and Code examples]]<br />
* [[FPC_Applications/Projects_Gallery]]<br />
* [[Operating Systems written in FPC]]<br />
* [[Using the Lazarus-ccr SVN repository]]<br />
* [[Case Studies]]<br />
* [https://lazarusccr.github.io/apps/ Lazarus Apps Showcase on GitHub]<br />
<br />
== Components and Libraries ==<br />
<br />
=== 5dpo ===<br />
[[5dpo]] Component Library is a set of components developed by the [http://www.fe.up.pt/~robosoc 5dpo Robotic Soccer Team]. It provides a visual serial port (TSdpoSerial) implementation of [[Projects_using_Lazarus#Synaser|Synaser]], an IEEE1394 camera (TSdpoVideo1394) component, an [http://linux-uvc.berlios.de/ UVC video] driver component (TSdpoVideo4L2) for webcams, a Gtk fast painting form (TSdpoFastForm) and a Joystick (TSdpoJoystick) component.<br />
<br />
=== ACBr ===<br />
[https://sourceforge.net/projects/acbr/ Project ACBr] Suite Components facing Commercial Automation. Working with ECF, TEF, NF-e, CT-e, MDF-e, SPED, NFS-e targeted to Brazilian Software. [http://www.projetoacbr.com.br/forum/index.php Fórum ACBr]. GNU Library or Lesser General Public License version 2.0 (LGPLv2).<br />
<br />
=== Audorra ===<br />
[http://audorra.sourceforge.net Audorra] is a digital audio library for Delphi and Free Pascal. Using a flexible plugin architecture, it allows you to exchange the audio backend (e.g. WaveOut, OpenAL), add protocol classes (e.g. file, http) and decoders. <br />
<br />
=== BrasLib ===<br />
[http://br.groups.yahoo.com/group/BrasLib-devel/ BrasLib] is a new report component for Lazarus under development by Brazilian programmers. <br />
<br />
=== Brook Framework ===<br />
<br />
[[Brook Framework]] is the Free Pascal framework for web applications. It's complete: simple actions or configurable actions for database access, advanced routing features, wizard for Lazarus, support for i18n, high compatibility with [[JSON]] structures, easy and elegant REST implementation, plugins etc...<br />
<br />
=== CUPS ===<br />
[http://cups4lazarus.sourceforge.net/ CUPS for Lazarus] is bindings for Pascal to use the CUPS (Common UNIX Printing System) libraries. With some dialogs for select printer, setup printer, setup printer jobs.<br />
<br />
{{Note|This package is deprecated, Cups for Lazarus is now integrated in Printers4Lazarus package which is included with Lazarus. --[[User:Jesusrmx|jesusrmx]] 2006 }}<br />
<br />
=== DXScene ===<br />
<br />
[http://www.ksdev.com DXScene] is a 3D hardware accelerated graphics library. It increases the speed of the development of all graphical applications. It provides: a 3D and 2D graphical editor integrated in IDE, 3D shapes and transformation, 2D graphical objects, simplify animation, advanced windows and controls, maximum performance, skinning engine, bitmap effects, 3DS file converter. DXScene can be used as development tool for standard, multimedia, SCADA, GIS, CAD and KIOSK applications. It support Windows, Mac OS X and Linux. For more info see [http://www.ksdev.com www.ksdev.com].<br />
<br />
=== Extended, Man/XML Frames ===<br />
<br />
[http://www.extended.in Extended] components are data and ini customized components. It contains relationships management components to use with your data software and for [https://bitbucket.org/matthieugiroux/virtualdbtreeex-interface-with-checks-entirely-created-with/src VirtualDbTreeEx]. There are also invisible components for pictures' translation, extracting and copying. There is also an update component with its ini creating project. With Extended you can create reports quickly from data, Virtual Trees or tdbgrids.<br />
<br />
Extended uses now GPL license.<br />
<br />
[https://bitbucket.org/matthieugiroux/manframes-rad-rich-management-framework-with-main-and-child Man Frames] are management components for tables. Some data or property forms can manage some kinds of Datasets. A prepared software with user management and functions management lets you [http://en.wikipedia.org/wiki/Model-driven_engineering#Tools quickly create a management software with an engine, without creating source]. It depends on [https://bitbucket.org/matthieugiroux/extended Extended] components. <br />
<br />
[https://bitbucket.org/matthieugiroux/very-rapid-applications-management-development-framework XML Frames], a [http://www.vrad.fr VRAD] Framework, lets you create a management software from [https://fr.wikipedia.org/wiki/Business_Process_Model_and_Notation BPMN 2 XML] files. On Windows, Linux and Mac OSX. Free components are now with GPL license.<br />
<br />
[[File:2010-10_extended.png|380px]][[File:2010-10 xmlframes.png|350px]]<br />
<br />
=== Eye-Candy Controls ===<br />
[[Eye-Candy Controls]] - set of visual controls written for Lazarus. More than twenty advanced controls.<br />
<br />
=== FlashEngine ===<br />
[http://www.ksdev.com FlashEngine] is a set of components for Delphi, C++ Builder and Lazarus which add extra features to Adobe Flash (ActiveX or Netscape plugin)- such as loading from any sources, grab real 32-RGBA frames, real transparency playing. It supports Windows and Mac OS X. For more info see [http://www.ksdev.com www.ksdev.com].<br />
<br />
=== fpctwit ===<br />
[https://bitbucket.org/reiniero/fpctwit fpctwit] is a plurk, Twitter and OAuthv1 library with example programs (console and GUI). It's a framework that implements the [http://en.wikipedia.org/wiki/Oauth Oauthv1] authorization protocol.<br />
<br />
The OAuth library (and the Twitter and plurk libraries using that) uses the Synapse network units for easy communication, but can easily be adapted for other network layers. It supports OAuthv1 secure authentication and SSL/TLS encryption.<br />
<br />
The library uses modified fpJSON units to allow getting UTF8 data out of the JSON data with Tweets returned from Twitter (for FPC trunk, the FPC units are used as Michael Van Canneyt added support for UTF8 in trunk).<br />
<br />
Functionality includes: getting tweets using the Search API, tweeting, getting username info, authenticating using PIN/OOB or preset credentials (consumerkey+secret,authtoken+secret).<br />
<br />
The twitter console demo, fpctwit, also demonstrates the Streaming API to process and show Tweets and deletion messages.<br />
<br />
There is a plurk console demo that demonstrates the functionality in the plurk library.<br />
<br />
The plurk and Twitter libraries use the included OAuth1 unit that provides OAuth1 authentication. This authentication mechanism is also used for other service providers. <br />
<br />
The Lazarus demo application, imaginatively named fpctwitGUI, is shown in the Lazarus Application Gallery at [[Lazarus_Application_Gallery#fpctwitGUI|fpctwitGUI]]<br />
<br />
=== Greyhound ===<br />
[https://github.com/mdbs99/Greyhound Greyhound] is a tiny ORM-ish for Free Pascal. It is fast, clean and simple to use.<br />
<br />
=== GTK2forpascal ===<br />
Mattias Gaertner's [http://sourceforge.net/projects/gtk2forpascal/ gtk2forpascal project] is developing the bindings for pascal to use the gtk2 libraries (gimp tool kit). Supported Languages are [[Free Pascal]] and Kylix and the bindings are intended to work under Linux, FreeBSD and Win32. These bindings are now also part of the packages supplied with fpc.<br />
<br />
=== Habari ActiveMQ Client / Habari OpenMQ Client ===<br />
[https://www.habarisoft.com/ Habari ActiveMQ Client] is a library (and components) for Delphi(tm) 6 to 2009 and Free Pascal which provides easy access to [http://activemq.apache.org/ Apache ActiveMQ], the most popular and powerful open source Message Broker.<br />
With Habari ActiveMQ Client, applications can connect to Apache ActiveMQ servers, subscribe to queues and topics, send and receive messages and objects, and work with transactions. The library follows the specification of the [http://en.wikipedia.org/wiki/Java_Message_Service JMS API] for Message Oriented Middleware. The communication layer supports Synapse and Internet Direct (Indy) for Lazarus.<br />
<br />
[https://www.habarisoft.com/ Habari OpenMQ Client] is a library for Delphi(tm) 6 to 2009 and Free Pascal which provides easy access to the [https://mq.dev.java.net/about.html Open Message Queue (OpenMQ)] Message Broker, a very compact, fast and easy to use message queue system. OpenMQ is part of the GlassFish(tm) application server for the Java(tm) platform. The library follows the specification of the [http://en.wikipedia.org/wiki/Java_Message_Service JMS] API for Message Oriented Middleware. The communication layer supports Synapse and Internet Direct (Indy) for Lazarus.<br />
<br />
=== Indy for lazarus ===<br />
Begun only a short while ago, this project has as an ambition to port the 119 Indy components from Delphi/Kylix to FPC/Lazarus.<br />
See [http://indy4lazarus.sourceforge.net/ Indy for Lazarus project] and a <br />
[http://indy4lazarus.sourceforge.net/images/img1_1.jpg screenshot].<br />
<br />
=== Internet Tools ===<br />
The [http://www.benibela.de/sources_en.html#internettools Internet Tools] are a set of units, which should contain everything you need to interact with the www. Includes html parsers with a sax and dom-like interfaces, an XPath 2 / XQuery interpreter, CSS 3 selectors, pattern-matching xml templates, and a http/s connection wrapper around synapse/wininet. Compare the [[Internet Tools | examples here]].<br />
<br />
=== KControls ===<br />
[[KControls]] is a set of powerful components for Delphi and Lazarus. Main components are: KGrid/KDbGrid - grid components, KMemo - rich edit component, KHexEditor - hexadecimal editor. Freeware with source.<br />
<br />
=== LazAutoUpdate ===<br />
[[LazAutoUpdater|Laz Auto Update]] is a visual drop-in component for the Lazarus/FPC IDE to make updating your application easier and simpler.<br />
It is aimed at Lazarus Windows developers who host their project in SourceForge.<br />
*Drop-in the component, set one property (your sourceforge project name) and call these simple methods:<br />
If LazAutoUpdate.NewVersionAvailable then...<br />
LazAutoUpdate.DownloadNewVersion<br />
LazAutoUpdate.UpdateToNewVersion<br />
*..and in your form.activate code:<br />
LazAutoUpdate.ShowWhatsNewIfAvailable<br />
*You (the developer) have plenty of control over how the component behaves, yet it is simple to use.<br />
*End-users see the updating process as simple and transparent<br />
<br />
=== Lazarus xPL Libraries ===<br />
[http://glh33.free.fr glh33 Home Automation] is a complete set of tools and foundation library developped in Lazarus for portability purpose under Linux and Windows. xPL Hub, sender, logger, weather listener, pascalscript.... Source code available on the xPL project's google code repository.<br />
<br />
=== LazReport ===<br />
[[LazReport Documentation|LazReport]] is a group of components to add reporting capabilities to applications, it uses a visual designer to create banded reports and includes a report engine with interpreter to run user scripts and a report previewer, report designer can be invoked at runtime.<br />
<br />
LazReport is based on FreeReport 2.32 and thanks to Fast Reports Inc. it's available under modified LGPL, the same license as the Lazarus LCL.<br />
<br />
{{Note| Since Lazarus 0.9.23 revision 11950, LazReport source code is<br />
already included in Lazarus/components/lazreport directory. }}<br />
<br />
===movControl===<br />
movControl allows customizing the GUI (the position and dimension of GUI controls), during execution, by final users. The programer, component user, must place it on the form and make some settings with the Object Inspector. At the application execution, the end user will be able to move or re-size the components of this sheet as desired. [http://www.meddeb.net/movcontrol movControl web site].<br />
<br />
=== PUMA Repository ===<br />
The [[PUMA Repository]] (Pascal Units for Medical Applications) is a collection of Pascal units for health informatics. It is compatible with a range of Pascal dialects including Lazarus / Free Pascal, Delphi and winsoft Pocket Studio.<br />
<br />
=== Synapse ===<br />
The [http://www.ararat.cz/synapse/ Synapse Project] by Lukas Gebauer provides a serial port and synchronous TCP/IP Library.<br />
<br />
=== Synaser ===<br />
Library for serial communication (Linux, Windows) from the author of Synapse.<br />
homepage: http://www.ararat.cz/synapse/ (same as Synapse)<br />
<br />
=== The Icebox ===<br />
A lot of useful Lazarus/FPC related information and components can be found on Tony Maro's [http://tony.maro.net/ Icebox site] (link expired). His TMPack, Checkbook Tracker and RDP Frontend application are all excellent examples of the quality components and applications that Lazarus is capable of producing.<br />
<br />
=== The Light Pascal Toolkit (LPTK) ===<br />
The goal of the [http://lptk.sourceforge.net/ Light Pascal Toolkit] Project is to create a free object pascal toolkit for linux and windows GUI development. It looks pretty interesting... check out the [http://lptk.sourceforge.net/screenshots.php screenshots]!<br />
<br />
=== TTreeListView === <br />
The [http://www.benibela.de/components_en.html#treelistview tree list view] is the combination of a TTreeView and a TListView, i.e. a tree with columns. It is custom drawn and therefore completely platform independent. (Windows, Linux gtk2, 32/64bit. Didn't test mac/qt through)<br />
<br />
=== VGScene ===<br />
[http://www.ksdev.com VGScene] speeds the development of all graphical application, providing: a graphical editor integrated in IDE, graphical objects, simplify animation, advanced windows and controls, maximum performance, skinning engine, bitmap effects. VGScene can be used as development tools for standard, multimedia, SCADA, GIS, CAD and KIOSK applications. Support Windows, Mac OS X and Linux. For more info see [http://www.ksdev.com www.ksdev.com].<br />
<br />
=== ZenGL ===<br />
[http://www.zengl.org ZenGL] is an open source library with tools, which helps to develop games and interactive application for different platforms.<br />
<br />
== Multimedia ==<br />
<br />
=== Audio X ===<br />
[http://www.ullihome.de Audio X] is a media management tool, that organizes and sorts your media without a database so everything is ever actual. A lot of audio formats are useable directly but you can also organize your LP or CD collection with it, it stores the data in XML Files so they are viewable also with a webbrowser ... <br />
<br />
=== Cactus Jukebox ===<br />
[http://www.cactusjukebox.org Cactus] is an audio player that comes with a database to organize your mp3 file collection. It is currently available for linux and win32. <br />
<br />
Since version 0.3 it supports managing and uploading files on a mobile player.<br />
<br />
=== CPickSniff ===<br />
[http://sourceforge.net/projects/cpicksniff2/ CPickSniff] is a multiplatform color picker.<br />
<br />
=== gdvdslides ===<br />
[http://rimrocksoftware.com/node/2 gdvdslides] is a Linux graphical user interface for the command line program dvd-slideshow, which allows you to create a video from a set of video clips, JPEG image files and audio files. gdvdslides supports slide transitions, title slides, background images and multiple audio tracks. It also allows cropping, Ken Burns effect and scrolling slide effects. gdvdslides comes with complete documentation and tutorial.<br />
<br />
=== GLScript ===<br />
[http://glscript.sourceforge.net GLScript] is a simple, free, open-source scripting language for developing 3D games and animations. (GL stands for Graphics Library, I.E. Graphics Library Scripting) There are currently plans to have a code-converter to make scripts compilable with lazarus/fpc and other languages to make a standalone executable from your creation.<br />
<br />
=== Greenfish Icon Editor Pro ===<br />
[http://greenfishsoftware.blogspot.hu/2012/07/greenfish-icon-editor-pro.html Greenfish Icon Editor Pro] is an open source pixelgraphic editor for creating icons, cursors, animations, pixel art, etc.<br />
<br />
=== hgdc-x ===<br />
hgdc-x is a cross-platform desktop client for the Hackathon Günther Daemon music player project. It's Github repository can be found at (https://github.com/tristan2468/hgdc-x). It requires a correctly installed and configured hgd server. The official github repository for the server can be found at (https://github.com/vext01/hgd).<br />
<br />
=== KSP Sound Player ===<br />
[https://code.google.com/p/kspnew/ KSP] is an easy in use yet powerful audio player supporting multiple file formats and features like dynamic playlists, bookmarking or network streaming. It also used to be hosted on [http://ksplayer.com this site].<br />
<br />
=== LazAudioPlayer ===<br />
[https://sourceforge.net/projects/lazaudioplayer/ LazAudioPlayer] is a simple mp3 player.<br />
<br />
[[Image:lazaudioplayer.jpeg|350px]]<br />
<br />
Features:<br />
<br />
* logarithmic volume adjustment with loudness<br />
* professional 31 band graphic equalizer<br />
* stereo width control<br />
* echo volume control<br />
* playlist viewer<br />
* user defined equalizer settings<br />
* FFT display<br />
<br />
=== LazPaint ===<br />
[http://sourceforge.net/projects/lazpaint/ LazPaint] is an image manipulation application.<br />
<br />
=== LazPlayer ===<br />
[https://sourceforge.net/projects/lazplayer/ LazPlayer] is a simple mp3 player.<br />
<br />
[[Image:lazplayer.PNG]]<br />
<br />
Features:<br />
<br />
* logarithmic volume adjustment with loudness<br />
* 10 band graphic equalizer<br />
* stereo width control<br />
* playlist viewer<br />
* loop ans shuffle mode <br />
* intelligent playing favorite tracks<br />
<br />
=== miXimum ===<br />
[https://sites.google.com/site/fiensprototyping miXimum] is the DJ's best friend.<br />
miXimum plays and mixes wav, mp*, ogg and mod audio files.<br />
On WINDOWS, LINUX and MAC OSX.<br />
<br />
[[File:miximum1.jpg]]<br />
<br />
=== Music Player by Freebyte.com ===<br />
Music Player by Freebyte.com is a freeware no-frills music player designed for Linux. It supports MP3, Wav, OGG and AIFF files. Created by [http://www.freebyte.com Freebyte.com] using Lazarus, Free Pascal and the Bass audio library on Ubuntu 10.x<br />
<br />
Program home page: http://www.freebyte.com/music_player/<br />
<br />
=== OggBase ===<br />
[http://sourceforge.net/projects/oggbase/ OggBase] is a Free Pascal/Lazarus program for managing your Ogg-Vorbis files in a Database.<br />
<br />
=== Pi Vision ===<br />
[https://github.com/local-vision/Pi-Vision Pi Vision] is a graphical user interface for the [[Lazarus on Raspberry Pi|Raspberry Pi]] camera module.<br />
<br />
=== PicturesToExe Mac OS X Slideshows ===<br />
[http://www.wnsoft.com WnSoft] is using Lazarus IDE to develop FPC-based slideshow viewer for Mac OS X, and planned PicturesToExe for OSX.<br />
<br />
<br />
=== Tonopol-Trainer ===<br />
[http://sourceforge.net/projects/tonopoltrainer/files/ sourceforge] is an music-analyzer and trainer for musicans like best-practice, but many more functions. Source available. <br />
<br />
[[image:tptrainer.png|800px]]<br />
<br />
=== Web Player Creator ===<br />
<br />
Static HTML5 and Flash auto creating structure with support of OGG, MP3, WMA. You can add text in each directory. You can also delete structure or converted files if you want.<br />
<br />
[http://www.devenircreatif.com/Music/Wilhelm%20FURTW%C3%84NGLER/index.htm Démo]<br />
<br />
[https://bitbucket.org/matthieugiroux/lazarus-html-5-static-web-audio-player-creator-for-best/downloads Download]<br />
<br />
=== WinFF ===<br />
[http://www.winff.org WinFF] is a GUI for the command line video converter, FFMPEG. It will convert most any video file that FFmpeg will convert. WinFF does multiple files in multiple formats at one time. You can for example convert mpeg's, flv's, and mov's, all into avi's all at once. WinFF is available for Windows 95, 98 , ME, NT, XP, VISTA, and Debian, Ubuntu, Redhat based GNU/Linux distributions.<br />
<br />
== Games ==<br />
<br />
=== 30 Seconds Free Software ===<br />
[http://code.google.com/p/30seconds 30 Seconds] is a software package that creates cards for the [http://en.wikipedia.org/wiki/30_Seconds_(game) 30 Seconds] board game. It also has a playing interface if you want to play on your laptop / PC (and hopefully soon WinCE devices). <br />
<br />
=== Castle Game Engine ===<br />
[[Castle Game Engine]] ([http://castle-engine.sourceforge.net/ project page]) is a 3D open-source game engine. The engine was developed from the beginning using Free Pascal (we have also Lazarus components) in nice and clean ObjectPascal code. We support many 3D model formats, including [http://castle-engine.sourceforge.net/vrml_x3d.php VRML/X3D], Collada, 3DS and many others. Tools and games using the engine include: <br />
* [http://castle-engine.sourceforge.net/view3dscene.php view3dscene - 3D model viewer, VRML/X3D browser], <br />
* [http://castle-engine.sourceforge.net/castle.php The Castle - FPS game in a dark fantasy world], <br />
* [http://castle-engine.sourceforge.net/darkest_before_dawn.php Darkest Before the Dawn - small scary 3D game for standalone and Android (also on Google Play)]<br />
<br />
=== Daring Apprentice ===<br />
[http://daringapprentice.wikispaces.com Daring Apprentice] is a 3d [http://www.wizards.com/magic/ Magic: The Gathering] tabletop. It uses GLScene, and lNet.<br />
<br />
=== Dreams of a Geisha ===<br />
Take a journey through the magical and wonderful world of Geisha. Help Ichisumi in this incredible adventure to reopen the temples of Geisha and restore a world of beauty and passion. Dive into this engaging Match 3 game with beautiful scenery and relaxing music. Overcome obstacles, collect puzzle pieces, and be prepared to solve challenging puzzles in [http://www.dreamsofageisha.com Dreams of a Geisha]!<br />
* Fantastic gameplay<br />
* Exciting action<br />
* Restore a wonderful world!<br />
<br />
Powered by Lazarus FPC, [http://www.zengl.org/ ZenGL], [http://www.phoenixlib.net/ PhoenixLib], [http://www.lua.org/ LUA] and [http://www.codeandweb.com/texturepacker TexturePacker].<br />
<br />
[[File:Dreams of a Geisha - Screenshot 1.jpg|border|270px]]<br />
[[File:Dreams of a Geisha - Screenshot 2.jpg|border|270px]]<br />
[[File:Dreams of a Geisha - Screenshot 3.jpg|border|270px]]<br />
<br />
Demo Version Available for<br />
[http://www.bigfishgames.com/download-games/12814/dreams-of-a-geisha/index.html Windows]<br />
[http://www.bigfishgames.com/download-games/13045/mac/dreams-of-a-geisha/index.html Mac]<br />
[http://itunes.apple.com/us/app/dreams-of-a-geisha/id460180656?mt=8 iPhone]<br />
[http://itunes.apple.com/us/app/dreams-of-a-geisha-hd/id459801505?mt=8 iPad]<br />
<br />
Developed by [http://www.greensaucegames.com Green Sauce Games] and Released by [http://www.bigfishgames.com Big Fish Games]<br />
<br />
=== Game Maker ===<br />
[http://www.yoyogames.com/gamemaker Game Maker] allows you to make computer games using easy to learn drag-and-drop actions. You can create professional looking games within very little time. You can make games with backgrounds, animated graphics, music and sound effects, and even 3D games! And when you've become more experienced, there is a built-in programming language, which gives you the full flexibility of creating games with Game Maker. What is best, is the fact that Game Maker can be used free of charge.<br />
<br />
Originally written in Delphi, Lazarus/Free Pascal was used to port it from Win32 to Mac OS X and could be used in future for Linux and other platforms.<br />
<br />
=== Juegos Iniciales ===<br />
<br />
[http://juegosenlazaruscostarricenses.com Juegos Iniciales] are a small collection of 3D tutorial games in<br />
Lazarus, SDL and FreePascal. In 2016, there were only four games:<br />
[http://origamisiniciales.juegosenlazaruscostarricenses.com Origamis Iniciales], <br />
[http://bloquesiniciales.juegosenlazaruscostarricenses.com Bloques Iniciales], <br />
[http://nudosiniciales.juegosenlazaruscostarricenses.com Nudos Iniciales],<br />
[http://palitos-iniciales.juegosenlazaruscostarricenses.com Palitos Iniciales].<br />
<br />
=== LazGobang ===<br />
[http://www.fpccn.com/read.php?tid=1399 LazGobang] is a Gobang game, powered by lazarus. <br />
[http://www.fpccn.com/attachment/photo/Mon_1106/31_c35013086418153b1581bc663bece.png Screen Shot1], <br />
[http://www.fpccn.com/attachment/photo/Mon_1106/31_49501308641990eaa7dd3b88e869e.png Screen Shot2], <br />
[http://www.fpccn.com/attachment/photo/Mon_1106/31_f197130864204448e6b393130adb6.png Screen Shot3].<br />
<br />
[http://files.cnblogs.com/lazarus/LazGobang.rar Download it].<br />
<br />
=== LBP Level Logger ===<br />
[http://code.google.com/p/lbplevellogger/ LBP Level Logger] is a small system tray application designed to log [http://www.littlebigplanet.com/ LittleBigPlanet] level statistics from [http://lbp.me/ lbp.me] over time for graphing/visualisation. It is written in Free Pascal/Lazarus.<br />
[[File:lbplevellogger-screenshot.png]]<br />
<br />
=== Mundo Medieval 3D MMORPG ===<br />
<br />
Featuring a virtual world of more than 1.000.000 m2, plus caves and hell sceneries, 17 NPCs, 21 kinds of monsters, including 7 bosses, 58 different items and 100 quests, this is a really large game made with Freepascal/Lazarus. The project is 100% Free Software, both code and media are licensed under GPL. The project sites are [http://www.gamemundo.com/ http://www.gamemundo.com/] and [http://sourceforge.net/projects/gamemundo/ http://sourceforge.net/projects/gamemundo/].<br />
<br />
<br />
[[File:Mundo - Screenshot 1.png|border|270px]]<br />
[[File:Mundo - Screenshot 2.png|border|270px]]<br />
[[File:Mundo - Screenshot 3.png|border|270px]]<br />
<br />
=== Pnigin (a Pengo Remake) ===<br />
Pnigin is an advanced remake of the 80's arcade classic Pengo.<br />
<br />
The project was made from scratch, using all original artwork and music. The project used Delphi 5 personal, Lazarus and Free Pascal for development.<br />
<br />
As the project is currently in a beta stage, there is no working demo yet. It is expected that a playable demo is released in summer 2008.<br />
<br />
=== Slot Cars - The Video Game ===<br />
“Slot Cars – The Video Game“ is an Indie, Racing, Simulation game with a tracks editor.<br />
<br />
<center>[[Image:SlotCarsTheVideoGame SS 02.jpg]]</center><br />
<br />
With “Slot Cars – The Video Game“ you can create<sup>*</sup> and edit<sup>*</sup> your own tracks and then play with these, also with a friend in a local split screen<sup>**</sup>.<br />
<br />
It is also possible to save<sup>**</sup> and reload<sup>**</sup> your creations.<br />
<br />
You can listen your own “shuffled music” in menu or in game, just copying MP3 into the relative directories<sup>*</sup>.<br />
<br />
<sup>* See manual for detail.</sup><br />
<br />
<sup>** Only in Full version.</sup><br />
<br />
“Slot Cars – The Video Game” use GLScene (so, OpenGL) for graphics, OpenAL for 3D audio and Newton Game Dynamics to manage real time physics.<br />
Nothing is pre-calculated.<br />
<br />
Powered by '''Lazarus''' & '''GLScene'''.<br />
<br />
Final graphics and local multiplayer (splitscreen):<br />
<br />
[http://www.youtube.com/watch?v=JL1W7jfym-4 About graphics and multiplayer]<br />
<br />
Official Trailer:<br />
<br />
[http://www.youtube.com/watch?v=-m8v2txY2Ck About gameplay]<br />
<br />
Here two videos also:<br />
<br />
[http://www.youtube.com/watch?v=x9w261bvzzw About gameplay]<br />
<br />
[http://www.youtube.com/watch?v=PNal6vb5m9Y About editor and gameplay]<br />
<br />
You can find info and the DEMO to download [http://www.kjow.net HERE]<br />
<br />
=== Retro Ski Run ===<br />
[https://sourceforge.net/projects/retroskirun/ Retro Ski Run] is a simple ski game for Windows 32/64bit and Linux 32/64-bit.<br />
<br />
[[Image:ss_rsrStartScreen.jpg]]<br />
<br />
=== ZWordQuiz ===<br />
ZWordQuiz is the remake of the famous Windows CE Software KWordQuiz.<br />
With ZWordQuiz you can use the dictionaries in the format kvtml KWordQuiz to train your memory.<br />
<br/><br />
Developer by Jonathan<br />
<br/><br />
[http://www.magicdev.org/zwordquiz_en WebSite]<br />
=== Bomber Kat ===<br />
Commercial game developed with FPC for iOS (both arm and arm64 platforms are supported). <br />
<br />
[[ZenGL]] based. Lazarus has been used as a primary IDE.<br />
<br />
Link: [https://itunes.apple.com/app/bomber-kat/id1109783786?ls=1&mt=8 App Store]<br />
<br />
== Web ==<br />
<br />
=== ExtPascal ===<br />
[http://extpascal.googlecode.com ExtPascal] is an Ext JS wrapper. It lets you use the ExtJS from Object Pascal commands issued by the server. That brings the structure and strict syntax of the Object Pascal for programming the web browser.<br />
<br />
=== TeamBBS ===<br />
[https://bergertime.eu TeamBBS] is a modern bulletin board system. Installed in 10 minutes, it might be the forum for classes or clubs. Content can be text, images or links.<BR> <br />
If everything is said, TeamBBS builds a conclusion and is uninstalled in 5 minutes. Location- and Online- views deliver "community spirit". <BR><br />
Source code included (German/English). Please join us, we need a French and Italian version.<br />
<br />
=== Whic ===<br />
[https://whic.ru/en/ Whic] is a bulk domains checker. Does not require installation. There are free (whic free) and paid (whic pro) version<BR> <br />
Whic free scans .COM, .RU/.SU/.РФ domains for availability and whois data. Whic pro has more advanced functionality<BR><br />
The software is multilingual: currently supports English, Russian and Chineese languages.<br />
<br />
== Education and Scientific ==<br />
<br />
=== Albireo ===<br />
[http://albireo.gotozero.de Albireo] is a small-footprint astronomy software for hobby and amateur astronomers. Albireo can be used as an observation documentation and object identification tool. <br />
It should be working on any MS Windows based PC.<br />
<br />
[[Image:Albireo.jpg|500px|Dynamic Star Map]]<br />
<br />
=== Ancestromania ===<br />
<br />
<br />
[http://ancestromania.net Ancestromania] is a fully LGPL genealogy software. It is user-friendly. You can import and export to Gedcom. You can export to Geneanet and to a web site. There is a great graphical tree, with fast classic trees. There are a lot of following documents.<br />
<br />
[http://genealogie.liberlog.fr/Family-trees Ancestroweb] creates a [http://matthieu.giroux.free.fr/genealogie/default.htm static genealogy's web site]. It is french, but can be translated easily. It is part of Ancestromania.<br />
<br />
[[File:Ancestromania.jpg|830px]][[File:2012-04 Ancestroweb.jpg|380px]][[File:2012-05 Ancestroweb carte.jpg|300px]]<br />
<br />
=== ApertaLetra ===<br />
[http://wp.me/pWoqh-28 ApertaLetra] is a text editor colorful and cheerful, where available, without leaving the context of software: formatting, new / open / save, cut / copy / paste and print. [http://sourceforge.net/projects/apletra Sourceforge page]<br />
<br />
=== ApertaQuem ===<br />
[http://wp.me/pWoqh-3s ApertaQuem] is an electronic ballot box for mock elections. Is available to create any candidate with photo from the webcam or file. Exclusive use for school environments. [http://sourceforge.net/projects/apertaquem/ Sourceforge page]<br />
<br />
=== CityCAT ===<br />
[http://www.ncl.ac.uk/ceser/researchprogramme/integratedsystemsdemonstrationscities/citycaturbanfloodmodel/ CityCAT] (City Catchment Analysis Tool), developed at Newcastle University, is a unique software tool for modelling, analysis and visualisation of surface water flooding. It enables rapid assessment of combined pluvial and fluvial flood risk and effects of different flood alleviation measures.<br />
<br />
=== EzberIM ===<br />
[http://mehmetulukaya.wordpress.com/kelime-ezberim-kullanim-klavuzu/ EzberIM 1.4f] Kelime EzberIM provides you with a simple and efficient way to memorize the translations of words in various languages. Test your skills and improve your vocabulary with the help of this reliable and handy piece of software in an easy and interactive manner.[http://sourceforge.net/projects/ezberim/files/ezberim/ezberim-setup.exe/download EzberIM Download]<br />
<br />
[[Image:program_cevap_rapor.JPG|500px]]<br />
<br />
Also added some feautes for example picture samples, it gives a sentence with a picture also you can copy your pictures into directory.<br />
<br />
[[Image:Show_Pictures_As_Sample.png|500px]]<br />
<br />
Final feaute is make a sentence with mixed words:<br />
<br />
[[Image:make_sentences_new.png|500px]]<br />
<br />
=== FREE!ship Plus in Lazarus ===<br />
[https://github.com/markmal/freeship-plus-in-lazarus FREE!ship Plus in Lazarus] is further development of the ''FREE!ship Plus'' (by http://www.hydronship.net ) Windows program based on the free source code FREE!ship v3.x under GNU GPL license. This ''FREE!ship Plus'' application is migrated into free open source Lazarus / Free Pascal environment to promote further development in various platforms and for various platforms (OS and architectures).<br />
<br />
[[Image:FreeShip+qt.png|500px]]<br />
<br />
''FREE!ship Plus'' is designed for the full parametric analysis of resistance and power prediction for a ship and other calculations of hydrodynamics of vessels and underwater vehicles. ''FREE!ship Plus'' allows the designer to simulate and analyze condition of balance of a complex completely hull - rudders - keels - engine - propellers in different regimes and of service conditions of a ship. The analyzable system includes a hull, appendages, a propeller and the engine (i.e. resistance, power, a thrust and a torque), and also various service conditions (heaving, a wind, a shallow-water effect, a regime of tow / pushing, etc...).<br />
<br />
=== GroundCAD ===<br />
[http://www.groundcad.com GroundCAD] is new 2D CAD software for land surveying.<br />
working under windows,linux and mac os.<br />
GroundCAD supports many standard formats like : <br />
Ascii file(txt/csv),Autodesk dxf(ascii R12),Leica(gsi 8/16),Sokkia(sdr33) <br />
Topcon(fc4/gts7/xml/landxml),Google(kml) ...<br />
<br />
[[File:groundcad.jpg|500px]]<br />
[[File:layermanager.jpg|500px]]<br />
[[File:main-window-linux32.png|500px]]<br />
<br />
=== Harmonux ===<br />
[http://wiki.freepascal.org/User:MaxBorges Harmonux 0.1.4] Harmonic Analysis. Enter a table and get the harmonic function for the table. With the graphic of the points of the table and the function. Open Source GNU/GPL, pre-compiled for Linux and Windows.<br />
[[File:hamonux14.png|500px|thumb|center]]<br />
<br />
=== Jubarte ===<br />
[http://jubartecalc.googlepages.com/ Jubarte] aims to create a complete application suite to calculate and analyse the viability of telecommunication links. Jubarte is able to calculate links using Radio, Optical Fiber and Satellites, in the newer versions capabilities to calculate auxiliary systems is being added. Jubarte is being developped in Lazarus enviroment and exist binaries for Windows, Linux and OSX.<br />
<br />
===LibreAquarium===<br />
[http://www.libreaquarium.org] LibreAquarium is a GPLv3 aquarium management system for Windows, Linux and Mac with a Simulation Model System that tries to predict the pollutants evolution using the recorded analytics, the algae risk and many other features (Tasks control, Expenses, Analitics, Statistics). LibreAquarium has been made with a quality design in order to make easier the user experience. <br />
<br />
=== Manuscript4u ===<br />
[http://sourceforge.net/projects/manuscript4u/ Manuscript4u] is an open source project to read and search on the original languages of the Bible and on the translations. <br />
<br />
[[File:manuscript4u.png|500px|thumb|center|Manuscript4u: Bible search on original languages]]<br />
<br />
It has unique and easy way to do research on words in Greek and Hebrew. Learn the meaning of the word without dictionaries by the way that word was translated.<br />
<br />
In parallel, the original Hebrew/Aramaic (Old Testament) or Greek (New Testament) with your preferred translation.<br />
<br />
It comes with Bibles in Hebrew/Greek and English, Portuguese, Spanish but you can download scores of other translations. The Bible files can be downloaded from the UnboundBible site in many languages and converted to the format used by the program with an included conversion program. Pre compiled for Linux and Windows. <br />
<br />
Multi-language support. Currently English and Portuguese.<br />
<br />
Strong's dictionary for the Greek with one click.<br />
<br />
Links to sites like "The Blue Letter Bible" with further details about the word with one click.<br />
<br />
=== Master Maths ===<br />
[http://www.mastermaths.co.za Master Maths] specialises in computer based training and maths. The 3rd incarnation of our flagship product is developed using Lazarus, Firebird, [http://tiopf.sourceforge.net/ tiOPF v2] and the [http://fpgui.sourceforge.net/ fpGUI Toolkit]. The product has two parts. A GUI Administration application and a CGI Learner Browser (used to view and mark the teaching modules). The Learner Browser uses Adobe Flash extensively. The complete product runs under Linux and Windows.<br />
<br />
=== Morse Machine ===<br />
[http://downloads.tech-pro.net/morse-machine_tpmm01.html Morse Machine] is an implementation of "A Fully Automatic Morse Code Teaching Machine" first described in a May 1977 QST article of the same name by Ward Cunningham using Lazarus. The program teaches Morse code by sending a character and waiting for you to type what you heard on the keyboard. It grades your score and adds new characters when it sees that you are ready. The program is released under the GNU GPL version 2. Due to its use of the sound card, this implementation is for the Windows platform.<br />
<br />
=== MRIcroGL ===<br />
[http://www.mccauslandcenter.sc.edu/mricrogl/ MRIcroGL] is an opensource project that uses the graphics card (using OpenGL) to visualize and volume render medical images. It is hosted on the [http://www.nitrc.org/projects/mricrogl/ National Institutes of Health (NIH) Neuroimaging Informatics Tools and Resources Clearinghouse (NITRC)]. It can view images saved in NIfTI (.nii, .nii.gz, .hdr/.img), Bio-Rad Pic (.pic), NRRD, Philips (.par/.rec), ITK MetaImage (.mhd, .mha), AFNI (.head/.brik), Freesurfer (.mgh, .mgz), and many DICOM (extensions vary) formats. It is available for Windows, Linux and Mac OS X.<br />
<br />
[[Image:Shell.png|320px]]<br />
<br />
=== MRIcron ===<br />
[http://www.mricro.com/mricron/ MRIcron] is an opensource project that allows users to visualize and volume render medical images (MRI, CT, PET). It includes tools for lesion mapping, non parametric statistical analysis ([http://www.mricro.com/npm/ npm]), and conversion from the medical DICOM format to the scientific NIfTI format ([http://www.mricro.com/mricron/dcm2nii.html dcm2nii]). It is available for Windows, Linux and Mac OS X.<br />
<br />
[[Image:mricron.jpg|320px]]<br />
<br />
=== Nest-o-Patch ===<br />
[https://sourceforge.net/projects/nestopatch/?source=navbar Nest-o-Patch], software for the analysis of patch-clamp, two-electrode-voltage clamp and other electrophysiological data. Directly works with files created by HEKA Pulse or Patch-Master data aquisition software or with CSV and text files. Designed mostly for the analysis of single channel recordings, was nevertheless successfully used for whole-cell data analysis. Several academic papers were published with the use of this software.<br />
<br />
[[File:nest-o-patch trace.png|500px]] [[File:nest-o-patch amplitude histogram.png|380px]] [[File:nest-o-patch levels analysis.png|340px]] <br />
<br />
=== OctaveGUI ===<br />
[http://code.google.com/p/octave-gui/ OctaveGUI] is a(nother) GUI frontend for GNU Octave.<br />
<br />
=== OpenSIMPLY ===<br />
[http://opensimply.org Project home page] OpenSIMPLY is an open source free run-time library for discrete event simulation.<br />
The concept is suitable for the persons of a different programming and simulation experience.<br />
<br />
Both style of simulation: blocks and the low level are available. Adopted Simula models can be used too. The simulation blocks can be relocated on run-time, so the model is flexible for real time modifications. There are global, selected and deferred statistics gathering modes. <br />
<br />
Write model once: GUI and console output is implemented. Easy transfer of simulation data; remote simulation ready. <br />
<br />
The project is supplied with full documentation (HTML and CHM formats), insight help (pop-up hints) and tutorial.<br />
<br />
[[File:tutorial_demo_animation_s.gif|OpenSIMPLY tutorial demonstration example]]<br />
<br />
<br />
=== ProofTools ===<br />
[http://creativeandcritical.net/prooftools/ ProofTools] automatically and graphically generates semantic tableaux, also known as proof trees, semantic trees and analytic tableaux, generally used to test whether a formula is a logical truth, or whether a proof/argument is deductively valid. ProofTools can generate proof trees for propositional, predicate and (normal) modal logic. It is available for Windows, Linux and Mac OS X.<br />
<br />
[[File:ProofTools.png|ProofTools screenshot]]<br />
<br />
=== SignWriter ===<br />
[http://www.egyptologysoftware.com/software.html Signwriter] is an Ancient Egyptian Hieroglyphic Word Processor and Language tool. It is designed for creating and editing texts stored in MdC format and would be of interest to students, professionals, and anyone with an interest in the Ancient Egyptian Language.<br />
<br />
===SimSEE===<br />
[http://iie.fing.edu.uy/simsee/simsee SimSEE] is a platform for Simulation of Systems of Electrical Energy. Using SimSEE we can simulate the optimal operation of systems with hydroelectrical plants, hydro-reservoirs, fuel fired plants, wind farms and interconnections with other countries. The platform has a very sophisticated tool for modelling stochastic processes like river inflows, fuel prices, wind speed, etc. The software was developed in Spanish but we are working to support other languages (help is welcome).<br />
<br />
===SimThyr===<br />
[http://simthyr.sourceforge.net/ SimThyr] is a simulation program for the pituitary thyroid feedback control that is based on a parametrically isomorphic model of the overall system. It aims in a better insight into the dynamics of thyrotropic feedback. Applications of this program cover research, including development of hypotheses, and education of students in biology and medicine, nurses and patients.<br />
<br />
=== Skychart / Cartes du Ciel ===<br />
[http://www.ap-i.net/skychart Skychart] is a free software to draw a map of the night sky for the amateur astronomer from a bunch of stars and nebulae catalogs. It shows the position of the planets, simulates an eclipse and more. <br />
<br />
=== SPINA ===<br />
[http://spina.medical-cybernetics.de/en/ SPINA] is software for determining constant structure-parameters of endocrine feedback control systems from hormone levels obtained in vivo. The first version of this cybernetic approach allows for evualuating the functional status of the thyroid gland.<br />
<br />
=== SysLinea ===<br />
[http://wiki.freepascal.org/User:MaxBorges SysLinea 0.1.2] Solves Linear Systems and calculates Linear and Non linear Regression. It gives the Pearson and Spearman coefficients of correlation and the t-test. Open Source GNU/GPL, pre-compiled for Linux and Windows.<br />
[[File:syslinea12.png|500px|thumb|center|SysLinea 1.2 - Linear regression and non linear regression]]<br />
<br />
=== Turbo Circuit ===<br />
[[Turbo Circuit]] is a circuit drawing tool written in Lazarus / Free Pascal.<br />
<br />
=== Unified Life Models ===<br />
[http://www.biologie.ens.fr/~legendre/ulm/ulm.html ULM (Unified Life Models)] is an open-source software enabling the simulation and analysis of deterministic and stochastic discrete time dynamical systems for population dynamics modeling. It works natively on Windows, Linux and macOS.<br />
<br />
Models are described using a simple declaration language, close to the mathematical formulation. The system can be studied interactively by means of simple commands, producing convenient graphics and numerical results.<br />
<br />
[[Image:screenshot_ulm.png|320px]]<br />
<br />
=== Virtual Moon Atlas ===<br />
[http://ap-i.net/avl/en/start Virtual Moon Atlas] is software for lunar observation and study. It uses GLscene to give a realistic view of the Moon at any given location and time. The computations are done with the JPL ephemeris for extensive precision. It includes the most complete lunar formation database and picture library. The binary distribution is available for Windows, Mac and Linux.<br />
<br />
=== Xoctave ===<br />
[http://www.xoctave.com/ Xoctave] is a Human interface to GNU Octave. Xoctave encapsulates GNU Octave uses pipes and provides extra useful tools to make GNU Octave more easier to use. XOctave is written in Pascal using Lazarus front-end and Free Pascal (aka FPK Pascal) libraries. It uses synedit for syntax highlighting, and uses the Lazarus Component Library (LCL) is a set of visual and non-visual component classes over a Widget toolkit-dependent layer with multi-language support (English-Turkish)<br />
<br />
=== ZCAD ===<br />
[http://sourceforge.net/projects/zcad/?source=directory ZCAD] is a simple CAD program with support for file formats DXF.<br />
<br />
[[Image:Zcad.png|400px]]<br />
[[File:simplecad.PNG|400px]]<br />
<br />
== Management, Accounting and other Business Software ==<br />
<br />
=== AddressBook ===<br />
[http://www.cnblogs.com/lazarus/articles/2051659.html AddressBook] using the Sqlite store data, Support for Simplified Chinese, Traditional Chinese, English three languages. Support the list shows, support to add, delete, right-click pop-up list menu to delete, change, check; Support importing csv, export csv file; import file format to export csv files can fill in; Contact the system into the same name as the default if there is to add a new record; Encoding exported file system based on user language encoding decisions; support the dynamic selection of countries or companies and added;<br />
support the department or group of dynamic selection and add; support the phonetic code or short code quick search contacts. For example: the Monkey King of the alphabet code, SWK. may enter the code in the alphabet Jane S, Sun will contact all the names are listed; [http://pic002.cnblogs.com/images/2011/300662/2011052008585591.png Screen Shot]<br />
<br />
=== Bilancio Facile ===<br />
[http://www.magicdev.org/bilanciofacile Bilancio Facile] is a simple application to manage the family budget.<br/> <br />
<br />
Developed by Jonathan.<br />
<br />
[[Image:winprev.jpg|Screen shot]]<br />
<br />
=== BRP-Software ===<br />
[http://www.brp-software.com/ BRP-Software] is a powerful and extremely flexible ERP System, that uses the Firebird database as backend. The first major release is in use with several different database structures to handle the needs of different business types. We have seperate databases for container logistics, laser cut metal production, software distribution and computershops. All databases use the same base application written in Lazarus.<br />
<br />
BRP Software is currently only focusing on the German speaking market, but it is developed for international usage. We plan to publish an international version in second half of 2013. There is a special free version already called Personal edition available now. This has only one restriction: it can not be used with more than one network user. This version includes the computershop database out of the box.<br />
<br />
[[File:BRP.gif]]<br />
<br />
=== Contact Contacts ===<br />
[http://www.trustfm.net/GeneralTools/SoftwareContactContacts.php Contact Contacts] is a free of charge portable and secure '''organizer''' that supports bulk emails and SMS.<br />
<br />
All data is stored '''securely''' into an encrypted database.<br />
<br />
The '''documentation''' is located [http://www.trustfm.net/GeneralTools/SoftwareContactContacts.php?page=ContactContactsTutorial here]<br />
<br />
[[Image:ContactContactsWin7.png]]<br />
<br />
=== DB2 Security Script importer ===<br />
[https://bitbucket.org/reiniero/db2securityscript/ DB2 Security script] is a script that runs on the DB2 database system and outputs audit/security-relevant information.<br />
<br />
Accompanying this script is a conversion program, OutputParser, that converts the script dump to a Microsoft Access database, Firebird embedded database, Microsoft Excel file, DBF, CSV etc. <br />
<br />
Although the program is fairly trivial, it shows:<br />
* how to use [[fpXMLXSDExport]] and [[FPSpreadsheet]] for output<br />
* how to create [[MS Access]] files programmatically<br />
* how to export datasets to another database<br />
* and some text processing/recognition and field creation on the input side.<br />
<br />
[[Image:DB2ParserCSVExport.png]]<br />
<br />
=== Eleman ===<br />
[http://www.linuxprogramlama.com/index.php?page=11 Eleman] is a accounting program with personnel, stock and billing capabilities. It is using firebird, zeosdbo and GPL licensed.<br />
<br />
=== ExVan ===<br />
[http://www.cforce.gr/sales.htm ExVan] is a WinCE/Win32 mobile invoicing program with batch data transfer for Greek ERP systems or standalone use.<br />
<br />
=== FXGest ===<br />
[http://www.magicdev.org/fxgest] is a simple application to manage the company budget. Based on Bilancio facile engine<br/> <br />
<br />
Developed by Jonathan.<br />
<br />
[[Image:cliente.jpg|Screen shot]]<br />
<br />
=== Gestinux ===<br />
[http://gestinux.net/mediawiki/index.php/Main_Page Gestinux] is a small accounting and invoicing software, to enter moves and import in various formats, to reconcile, and to print usual reports. You can produce quotes, order sand invoices, record customer payments. It is translated into english, spanish and italian from french, and can easily be translated to other languages. It is possible to setup specific reports for various countries. It runs on Linux, Windows and OS/X, using MySql, MariaDb and PostgreSQL.<br />
<br />
=== opsi ===<br />
[http://opsi.org/ opsi] is an open source Client Management System for Windows clients and is based on Linux servers.<br />
Key features:<br />
<br />
* Automatic OS installation (unattended or image based)<br />
* Automatic software distribution and patch management<br />
* Hardware and software inventories<br />
* multiple location support<br />
<br />
opsi server runs on Debian, Ubuntu, OpenSuse, SLES, CentOS, UCS and RHEL.<br />
We use Lazarus for the component opsi-winst which is the script driven generic setup program which does all the installations and system manipulations on the windows boxes.<br />
<br />
=== OutKafe ===<br />
[http://www.outkastsolutions.co.za/outkast/index.php?option=com_openwiki&Itemid=45&id=outkafe OutKafe] is a next-generation free and open source cybercafe management suite. It currently is running hundreds of cybercafe's at businesses, schools and other establishments around the world.<br />
<br />
=== PlanB ===<br />
[http://roberts.bplaced.net PlanB] is a Vehicle management program written using to Lazarus (Free Pascal) and MySQL Community Edition .<br />
<br />
Features :<br />
* Management of Mileage Log , Service , Registration , Mandatory Insurance documents .<br />
* Statistics : global , driver , company , mileage log , average fuel consumption, visited places.<br />
* Graphs : driver, vehicle .<br />
* Reminders for : oil , tachograph , fire extinguisher , leasing , driver health check , driver skills check , registration.<br />
* Unlimited number of Vehicle Groups ( example : Private, Company, Warehouse, VIP , etc. ) and Vehicles.<br />
* One window user interface , intelligently grouped together for easy everyday usage.<br />
* Can handle various Regional Settings without problems.<br />
* 100% UTF-8 (aka Unicode)<br />
* Handles multiple users at the same time. Items are locked when modifying to prevent database corruption.<br />
* Simple user rights : <br />
** administrator : unlimited access to program features<br />
** user : the one doing all the work , cannot add new users, view program statistics or unlock locked items.<br />
** guest : can only view statistics<br />
* Can export almost every table to EXCEL (2003 level) even without Excel being installed. <br />
* Can automatically resize tables to correct size to fit data being displayed,almost every table supports quick search.<br />
* Can print out every report to printer , or export to PDF . With Mileage Log Stats it can even mass export all vehicles in selected group to Excel file.<br />
* Uses MySQL Community Edition which is absolutely FREE.<br />
* Was written with Lazarus 1.2.2 using only FREE components.<br />
* Logs usage stats<br />
* Multilingual , right now : English, Hungarian, Serbian(Latin), German is supported .<br />
* All program related settings are stored in config files NOT in registry.<br />
* Tested on Windows XP,7,8,8.1 . (Windows 9x series not supported)<br />
<br />
Images :<br />
<br />
[[Image:planB1.png|715px|358px]]<br><br />
[[Image:planB2.png|320px|180px]]<br />
[[Image:planB3.png|320px|180px]]<br />
[[Image:planB4.png|320px|180px]]<br />
[[Image:planB5.png|320px|180px]]<br />
[[Image:planB6.png|320px|180px]]<br />
[[Image:planB7.png|320px|180px]]<br />
[[Image:planB8.png|320px|180px]]<br />
[[Image:planB9.png|320px|180px]]<br />
[[Image:planB10.png|320px|180px]]<br />
[[Image:planB11.png|320px|180px]]<br />
[[Image:planB12.png|320px|180px]]<br />
[[Image:planB13.png|320px|180px]]<br />
[[Image:planB14.png|320px|180px]]<br />
[[Image:planB15.png|320px|180px]]<br />
[[Image:planB16.png|320px|180px]]<br />
[[Image:planB17.png|320px|180px]]<br />
[[Image:planB18.png|320px|180px]]<br />
[[Image:planB19.png|320px|180px]]<br />
[[Image:planB20.png|320px|180px]]<br />
[[Image:planB21.png|320px|180px]]<br />
[[Image:planB22.png|320px|180px]]<br />
[[Image:planB23.png|320px|180px]]<br />
[[Image:planB24.png|320px|180px]]<br />
[[Image:planB25.png|320px|180px]]<br />
[[Image:planB26.png|320px|180px]]<br />
[[Image:planB27.png|320px|180px]]<br />
[[Image:planB28.png|320px|180px]]<br />
[[Image:planB29.png|320px|180px]]<br />
[[Image:planB30.png|320px|180px]]<br />
[[Image:planB31.png|320px|180px]]<br />
[[Image:planB32.png|320px|180px]]<br />
[[Image:planB33.png|320px|180px]]<br />
<br />
=== Postcode ===<br />
[https://bitbucket.org/reiniero/postcode/overview Postcode] is an open source program that looks up Dutch postcodes and adresses.<br />
It can look up postcodes when given street/street number/city and it can give the address when given a street number and postcode. Additionally, you can let it read in a CSV file or other delimited file and let it add missing information.<br />
<br />
Windows and Dutch language (source code commented in English).<br />
Uses a Firebird (embedded) database filled with postcode/address data from the Dutch government. <br />
<br />
Demonstrates use of <br />
* [[CsvDocument]] to read/write delimited files<br />
* drag and drop text content from other applications<br />
* regex library<br />
* Firebird stored procedures<br />
* database normalization<br />
* use of read-only transactions<br />
[[Image:ScreenshotPostcode.png|Postcode screenshot]]<br />
<br />
=== [http://free-erp.net/ Promet-ERP] ===<br />
[http://free-erp.net/ Promet-ERP] is a Small Business ERP System / Project management Solution / Mail Program / Document Management System. It can be used with most [http://free-erp.net/wiki/Promet-ERP/Databases major Database Systems] and on all major platforms (Windows, Linux, Mac OS X).<br><br />
[[Image:mainscreen windows.jpg|150x200px]][[Image:kalendar_windows.jpg|150x200px]][[Image:wiki_windows.jpg|150x200px]][[Image:mainscreen_linux.png|150x200px]][[Image:kalendar_linux.png|150x200px]][[Image:wiki_linux.png|150x200px]]<br />
<br />
=== Rednaxel RNGE3 ===<br />
[http://rednaxel.com/software/ RNGE3] is a Small-Medium Business ERP System (with WMS module) for brazilian companies. It emits Nota Fiscal Eletronica, the government-mandated electronic invoice.<br />
[[File:sshot-fat2.png]]<br />
<br />
=== RiXtoR ===<br />
[http://pietrobua.com/web/en/project/?name=rixtor RiXtoR] is a Point of Sale program specially designed for restaurants, working on both Windows and GNU/Linux Systems<br />
<br />
=== SilentCoder's Site ===<br />
[http://www.silentcoder.co.za silentcoder.co.za DireqCafe] is a complete and full full featured internet cafe solution for LTSP. A number of other useful lazarus programs can be found on A.J. Venter's site.<br />
<br />
=== TreePad Lite for Linux ===<br />
TreePad Lite for Linux is a freeware personal information manager.<br />
TreePad Lite can help you manage, store, edit, organize and browse any type of textual data, such as: notes, emails, articles, links, telephone extensions, addresses, scraps pasted from the Web, etc. Suitable for Linux. Created by [http://www.freebyte.com Freebyte.com] using Lazarus and Free Pascal on Ubuntu 10.x.<br />
<br />
Program home page: http://www.treepad.com/linux/treepadlite/<br />
<br />
=== TruckBites ===<br />
[http://www.truckbites.com TruckBites] is a business management software for independent trucking companies and owner/operators (for the USA.) Written under contract by [[user:Tonymaro | Tony Maro]] for both Linux and Windows for "Partners in Trucking, LLC". Still under development, anticipated release in the next few months.<br />
<br />
=== TurboCash plugins===<br />
[http://www.turbocash.net/wiki/index.php?title=Developer:Lazarus Open Source Accounting software] apparently allows writing plugins using Lazarus/FPC.<br />
The program itself is still written in Delphi: [http://sourceforge.net/projects/turbocash/ description on Sourceforge]<br />
<br />
=== WGVW ===<br />
[http://ceware.de/wgvw/ WGVW] is a freeware program for househould management. It includes capture of income and expenses (cash book) as well as recurrent items (recurring income/expenses). Apart from that it is possible to digitize documents and save account data. The program uses a Firebird database.<br />
<br />
=== Wireless Orders for Mini Bar Cafe ===<br />
Win32 TCP/IP Application Server, Win32 TCP/IP Client, WinCE TCP/IP Client.<br />
Using Lazarus and lNet we develop wireless ordering system for Mini Bar - Cafe.<br />
Print receipts directly to Cash Mashine.<br />
<br />
More Info ( http://www.cforce.gr/orders.htm )<br />
Demo ( http://www.cforce.gr/downloads/setupwodemo.exe )<br />
<br />
== Utilities and Miscellaneous ==<br />
<br />
=== Adnan Dictionary ===<br />
[http://sourceforge.net/projects/adnandict/ Adnan dictionary] is a light and open source dictionary based on the arabeyes.org database. It is available for both windows and linux and intends arab users.<br />
<br />
=== Advanced Password Generator ===<br />
[https://sourceforge.net/projects/apwg/ Advanced Password Generator] is a lightweight password generator tool to protect your security with randomly generated password. It runs on Windows and Linux. No installation required. This tool has GUI and command line version. Command line version is ideal for scripting. <br />
[[File:scrnsht1.png]]<br />
<br />
=== AksiIDE ===<br />
[http://www.aksiide.com AksiIDE] is a light freeware multi-platform text editor written in Lazarus.<br />
very useful for PHP developers.<br />
<br />
It has these features:<br />
* PHP Project Wizard<br />
* Portable Version Available<br />
* Live View Browser<br />
* Project Management<br />
* Class Generator<br />
* Integrated With Database Explorer (mysql + postgresql)<br />
* Database Browser<br />
* FTP Explorer<br />
* File Explorer<br />
* Code Explorer with Function List<br />
* Code Snippet<br />
* PHP Source Minifier<br />
* PHP Source Formatter<br />
* Syntax Checker<br />
* Multi Workspace Layout<br />
<br />
[[File:Aksi_IDE.jpeg|600px]]<br />
<br />
=== AlFileSearch ===<br />
[http://www.aldimsoft.ru/alfilesearch AlFileSearch] Simple file search utility which is able to quickly find files and folders on your PC running under Windows 10, 8, 7... It is able to sort out files and folders according to their properties (e.g. Modified Date). The results window supports Windows Explorer functionality: icons, context menus.<br />
<br />
=== Bar Generator ===<br />
[https://sourceforge.net/projects/bargenerator/ Bar Generator] is a simple QR, AZTEC and Data Matrix code generator.<br />
<br />
=== Becape ===<br />
[https://sourceforge.net/projects/becape/ Becape] is an open source backup tool aimed to personal/desktop usage. It does incremental backups and stores the backup info in a sqlite database allowing to restore the exact state of the backed files at a chosen date. It's fully written in Lazarus/Free Pascal.<br />
<br />
=== BioTray ===<br />
[https://sites.google.com/site/biotray/ BioTray], your Biorhythm in traybar.<br />
Biorhythm means rhythm of life.<br />
Our live is directed by emotional, intellectual and physical rhythms who begin at our birth.<br />
You will see on your traybar 4 new icons. They are : the emotional, the intellectual, the physical and the intuitive icon.<br />
How more the icon is filled, how big is your power. <br />
On WINDOWS, LINUX and MAC OSX.<br />
<br />
In traybar :<br />
<br />
[[File:biotray1.jpg]]<br />
<br />
[[File:biotray2.jpg]]<br />
<br />
=== CamMirror ===<br />
[http://www.cnblogs.com/lazarus/articles/2053748.html CamMirror] Using the camera as a mirror, it can be switched to several resolutions such as 320*240,640*480,800*600,1024*768 and full screen by clicking the tray icon menus. Windows only. <br />
<br />
=== CheckRide ===<br />
[https://bitbucket.org/reiniero/checkride/ CheckRide] is an open source remote control tool. It lets you take over the screen and keyboard of a remote computer. The helped person only needs to run the program, no firewall/router changes necessary. The helper does need to forward a port in her router.<br />
Features:<br />
* No configuration required for client, just click and be helped<br />
* Helper can use the tool to create a custom version of CheckRide that connects to her server. This way, the helped party only needs to download and run one program. Alternatively, the helper can distribute a configuration file for the same purpose.<br />
* Supports Windows UAC<br />
* Encrypted connection<br />
* Uses UltraVNC and stunnel programs to provide remote control and encryption<br />
* Supports Windows helped persons and helpers on Windows (CheckRideHelper.exe) and Linux (stunnel/vncviewer), probably OSX, too.<br />
* Can be used for free, both commercially and non-commercially. CheckRide wrapper is MIT licensed freeware: it can also be incorporated in commercial programs.<br />
<br />
Technical details: it uses an UltraVNC winvnc reverse connection and stunnel to create an encrypted connection. You can realize this by just using stunnel and vncviewer, so the helper side should be usable on Linux and OSX, too. For now, CheckRide itself has only been compiled on Windows; it will need some changes for other operating systems.<br />
<br />
Free Pascal techniques that are used:<br />
* Controlling external programs<br />
* Installing/deinstalling Windows services<br />
* "Poor man's resource": adding [[paszlib|zip]] files after exe with configuration data, UltraVNC, stunnel details<br />
* [[paszlib|Zipping/unzipping]] files<br />
* Using a manifest to request Administrator privileges/elevation<br />
* Handling command line options; multiple configuration mechanisms (embedded config file, config file in application directory, command line options)<br />
<br />
More details: see [https://bitbucket.org/reiniero/checkride/wiki/Home CheckRide wiki].<br />
<br />
Screenshots: [[Lazarus_Application_Gallery#CheckRide]]<br />
<br />
=== Convertor ===<br />
[https://hdrz.github.io/convertor/ Convertor] is a unit converter with a slightly different GUI. It aims to be as minimal and unobtrusive as possible, yet easy to use. It has many unit categories and units, and the units are defined in XML file which can be upgraded with no recompilation of the program.<br />
<br />
[[File:conv-min-layout.png]]<br />
<br />
=== CoreNet ISP Management ===<br />
[http://www.turbog.com/2012/04/24/corebil-net-isp-management/ CoreNet ISP Management] is a fully ISP management software package. It is a freeware Windows application.<br />
<br />
=== Coedit ===<br />
[https://github.com/BBasile/Coedit Coedit] is a small, open-source, cross-platform IDE for the [http://dlang.org/ D language].<br />
It features:<br />
* full featured project format and advanced project editor.<br />
* compile and run directly from the UI.<br />
* instant run (without saving, script-like).<br />
* synchronized edition in a block.<br />
* D2 syntax highlighter, folding, identifier markup.<br />
* module symbol list.<br />
* static libraries manager.<br />
* search and replace.<br />
* user-defined tools powered by a string interpolation system.<br />
* [https://github.com/Hackerpilot/DCD D Completion Daemon] integration for completion proposal and source code hints.<br />
* mini file browser.<br />
<br />
[[Image:coedit.linux.kde.png|640px]]<br />
<br />
[[Image:coedit.win7.png|640px]]<br />
<br />
=== CQRLOG ===<br />
[http://www.sourceforge.net/projects/cqrlog/ CQRLOG] is an advanced ham radio logger based on Firebird database. Provides radio control based on hamlib libraries (currently support of 140+ radio types and models), DX cluster connection, QRZ callbook (web version), a grayliner, ON6DP QSL manager database support and a most accurate country resolution algorithm based on country tables developed by OK1RR. CQRlog is strongly focused on easy operation and maintenance.<br />
<br />
=== CudaText Editor ===<br />
<br />
[[CudaText]] is advanced code editor for Win, Linux, OS X.<br />
<br />
[[File:cudatext.png]]<br />
<br />
=== Cut Your Time (CYT) ===<br />
[http://www.trustfm.net/GeneralTools/SoftwareCutYourTime.php Cut your time] is '''portable''' cross platform application for '''Windows''' and '''Linux''' that allows you to create reminders (alarms).<br />
<br />
The documentation for this application can be found [http://www.trustfm.net/GeneralTools/SoftwareCutYourTime.php?page=CutYourTimeTutorial here]<br />
<br />
[[File:CutYourTime.png]]<br />
<br />
=== dbmaker ===<br />
[http://www.rgsoftware.de dbmaker] is a database application using TDbf and LazReport. Its user interface language is german.<br />
<br />
=== Dedalu ===<br />
[http://dedalu.sourceforge.net/ Dedalu] is a collection of small and simple projects developed in Lazarus by Giuseppe Ridinò (aka Pepecito). They are games, editors, utilities, etc.<br />
<br />
=== Diacrit ===<br />
[http://www.sandrila.co.uk/diacrit/ Diacrit] is a utility to help with access to Unicode characters, choose the language you want. click the character button and paste into your application. Diacrit was first written in Turbo Pascal for Windows back in 1996, migrated to Delphi, and now upgraded to FP/Lazarus.<br />
<br />
=== Double Commander ===<br />
[http://sourceforge.net/projects/doublecmd/ Double Commander] is a cross platform open source file manager with two panels side by side. It is inspired by Total Commander and features some new ideas. <br />
<br />
=== Etiket ===<br />
[http://www.linuxprogramlama.com/index.php?page=12 Etiket] is a Label design and print tool. GPL licensed.<br />
<br />
=== ExPress ===<br />
[http://code.google.com/p/express-gui ExPress] is a GUI wrapper for UPX (Ultimate Packer for eXecutables).<br />
<br />
=== fenixsql ===<br />
[http://fblib.altervista.org fenixsql] is a simple admin tool for firebird sql database<br />
<br />
=== FileRecovery ===<br />
[http://www.grauonline.de/cmsimple2_6/en/?Solutions:Data_recovery_software FILERECOVERY] is a cross platform application to recover lost and deleted files and formatted disks. It supports all common file systems (FAT/NTFS/EXT2/3/ISO9660/HFS+) and comes with Mac Universal (Intel and PPC) and PC binaries. The application was originally written in Delphi and ported to FreePascal and Lazarus in 2010 and successfully shows that is it possible to develop system applications using modern development tools and the Pascal language.<br />
<br />
=== Fit Easily ===<br />
[http://fiteasily.com Fit Easily] is an online service for building the model of some experimental data, fitting its parameters and storing the results together with the data. Both of the cgi and the core was coded with Lazarus.<br />
<br />
=== fpcup ===<br />
[[fpcup]] is a tool that gets the current version of Free Pascal Compiler (FPC) and Lazarus IDE from their subversion repositories and compiles/installs them. It also compiles and installs whatever packages you want to install.<br />
It also creates a shortcut on your desktop that points to the new Lazarus installation.<br />
<br />
Meant to be used side by side with other FPC/Lazarus installations (it creates a separate primary config path directory for the new Lazarus installation, so it doesn't interfere with existing Lazarus installs)<br />
<br />
It's open source software, please see the code for the license.<br />
Runs on Windows and Linux; experimental support for OSX, FreeBSD.<br />
Run fpcup --help for command line options.<br />
<br />
See: [https://bitbucket.org/reiniero/fpcup fpcup repository and executables site]<br />
<br />
=== Free Pascal Operating System ===<br />
Interested in developing an OS with Free Pascal? This project can be used as a starting point (though incomplete and YOU ARE WELCOME to complete it :-)). Download it [http://code.google.com/p/fpos here](http://code.google.com/p/fpos).<br />
<br />
Another interesting project developed with Free Pascal called TORO can be found at: [http://toro.sourceforge.net TORO:] (http://toro.sourceforge.net).<br />
<br />
=== Golfml Applications ===<br />
[http://code.google.com/p/golfml/wiki/Welcome?tm=6 Golfml Applications] are aimed at golfers and golf course managers. The purpose of [http://code.google.com/p/golfml/ GolfML] is to provide a XML-based file format for the exchange of golf-related data. CourseWriter is an application for easily authoring golfml files and editing them. Golfml Reader is to display and test golfml data files. USGA/EGA Calculator has various golf handicapping functions, and uses golfml data files. Executables for Linux 64 and 32 bit and Windows 64 and 32-bit. Source code for all applications.<br />
<br />
=== GTK-Fireadmin ===<br />
A GTK based Firebird Administration tool using Firebird Objects and Lazarus Components is available [http://sourceforge.net/projects/gtkfireadmin/ here].<br />
<br />
=== Hagen - cross platform html generator ===<br />
<br />
<br />
[http://buch.im-ned.de/hagen Hagen] is a open source (lgpl) cross platform html generator (or client side cms). It supports the web developer by generating a website and writing the pages. For that purpose Hagen will automate as much tasks as it can.<br />
<br />
Features:<br />
<br />
*project management <br />
**variables, functions and settings <br />
**template based and (page) divisions <br />
**source files (.source) for content <br />
*editor <br />
**syntax highlighting <br />
**Markdown <br />
**search over all pages <br />
**insert colors, images, tables and references <br />
*repository <br />
**for data exchange <br />
**for templates <br />
*automation <br />
**automate menu generating <br />
**internal and user defined variables and funktions <br />
**printing page <br />
**generates whole website<br />
<br />
=== Heat Wizard ===<br />
[http://heatwizard.berlios.de/Heat_Wizard.html Heat Wizard] is a command line and GUI tool for the conversion of the voltage of a thermocouple to a temperature and vice versa (for Win32, Mac OS X, and Linux).<br />
<br />
=== Hexy ===<br />
A cross-platform tool for embedded C developers. It automatically converts binary files into C header files containing hexadecimal arrays for integration into embedded projects. The GitHub repo is at (https://github.com/tristan2468/Hexy).<br />
<br />
=== HJSplit for Linux ===<br />
HJSplit for Linux is a freeware file splitter. HJSplit supports file sizes of over 100 Gigabytes, Split, Join/Recombine, MD5 checksums, file-compare and "run without install". Suitable for Linux. Created by [http://www.freebyte.com Freebyte.com] using Lazarus and Free Pascal on Ubuntu 10.x.<br />
<br />
Program home page: http://www.hjsplit.org/linux/<br />
<br />
=== Incredimail to EML ===<br />
[http://www.dominion-it.co.za/development Incredimail2EML] is a util to convert Incredimail to EML format with attachments. The program will also try and continue converting even if it runs into a corrupt mailbox or messages. All messages are created in sub folders that represent the mailbox in Incredimail.<br />
<br />
[[Image:incredimail2eml.png|350px]]<br />
<br />
Program home page: http://www.dominion-it.co.za/development/incredimal_to_eml<br />
<br />
=== ISA Digital Osciloscope ===<br />
A graphical interface for a digital osciloscope. The osciloscope itself is an ISA card with a probe to measure waves. It works on both Windows and Linux. There is some information on how it is being built on [[Hardware Access]]. The full documentation (in English and Portuguese), screenshots and the source code of project can be downloaded [http://eletronicalivre.incubadora.fapesp.br/portal/english/oscilloscope/ here].<br />
<br />
=== JavaneseChess ===<br />
[https://bitbucket.org/leledumbo/javanese-chess JavaneseChess] is a Javanese chess game implementation. Available for Desktop platforms and Android (not feature complete yet).<br />
<br />
=== Kamouflage ===<br />
[http://wiki.lazarus.freepascal.org/User:Beli0135 Kamouflage] - Camouflage files into images<br />
<br />
=== LazEdit ===<br />
[[LazEdit]] is a simple text editor with tabbed document interface, supporting various syntax highlighters.<br />
It also has built-in functions for editing HTML.<br />
<br />
=== LazFileSplitter ===<br />
[http://br.geocities.com/antoniog123456/ LazFileSplitter] is a utility to split and merge big files.<br />
<br />
=== LazUpdater ===<br />
{{Warning|Does not seem to be maintained. A working alternative is fpcup}}<br />
From their web site: [http://forge.lazarusforum.de/projects/lazupdater/ LazUpdater] is a front-end for "svn" and "make" commands with some useful features to install or configure FPC and Lazarus.<br />
Once it's configured you update and rebuild FPC and Lazarus by just one click.<br />
With profiles you can manage different installations.<br />
Written for Linux, Windows, OSX.<br />
<br />
Licence: GPL v3<br />
<br />
=== LazVisual ===<br />
[http://br.geocities.com/antoniog123456/ LazVisual] is an external tool to include resources on executable file and set application icon.<br />
<br />
=== Mep LA ===<br />
[http://software.viamep.com/mepla/ Mep LA] is a simple and fast text editor. Key features: working with txt and html/php files, replacement and some customizable scripts with shortcuts. You can configure replacement and run it with a click or keyboard combination.<br />
<br />
=== MouseWiggler ===<br />
[https://bitbucket.org/leledumbo/mousewiggler MouseWiggler] is a simple application to periodically send message to make mouse move to prevent screen saver from executing (could be useful in a limited environment like a computer lab with auto logoff :p). The wiggle might not be visible because I give no delay between two messages to move the mouse from its current position to somewhere else and back.<br />
<br />
=== MUTerm (Rs232 Terminal) ===<br />
[http://mehmetulukaya.wordpress.com/2012/09/18/muterm-yazilimi-yuklenmeye-hazir/ MUTerm 0.1.1] <br />
MUTerm is a Com Port communication tool for external devices like as Modbus RTU , ASCII etc.<br />
Also you can write your communication routine witwh pascal script.<br />
[http://mehmetulukaya.files.wordpress.com/2012/09/main_screen.jpg Main Screen Shot]<br />
<br />
Additionally some TCP functions (client and server) added yet. <br />
It can be work with internet or localnetwork Modbus TCP or Http.<br />
[http://mehmetulukaya.files.wordpress.com/2012/09/tcp_screen.jpg TCP Connection Screen]<br />
<br />
[https://mehmetulukaya.files.wordpress.com/2016/04/ekran-gc3b6rc3bcntc3bcsc3bc-2016-04-08-091320.png Server screen]<br />
<br />
[[Image:tcp_screen.JPG|500px]]<br />
<br />
MUTerm created with by Lazarus 1.0~1.6 Linux and Windows<br />
[https://sourceforge.net/projects/muterm/files/muterm/ MUTerm Download]<br />
<br />
=== MyNotex ===<br />
[http://sites.google.com/site/mynotex/ MyNotex] is a free software for Gnu/Linux useful to take and to manage textual notes.<br />
<br />
[[Image:Screenshot_of_MyNotex_1.2.0_-_en.png|700px]]<br />
<br />
=== NotePas ===<br />
[http://code.google.com/p/notepas/ NotePas] is an open source multi-platform text editor written in Lazarus. It can be compiled for multiple platforms and widget sets.<br />
<br />
[[Image:notepas_-_code_folding.png]]<br />
<br />
[[Image:notepas_-_codefilter.png]]<br />
<br />
=== P.SEN ===<br />
[http://ancestorsoftware.co.nf/?page_id=14 P.SEN] is a utility to allow sending and receiving TCP and UDP packets and is available for Windows and Linux. It’s designed to be very easy to use while still providing enough features for power users to do what they need. It is completely free (no ads / no bundleware) and opensource. Some knowledge of a basic network protocols is a prerequisite to using it. Beyond that, P.SEN was designed to be very easy to use.<br />
<br />
[[Image:P_SEN_003.png|400px]]<br />
<br />
=== PasDoc ===<br />
[[PasDoc]] ([http://pasdoc.sourceforge.net/ webpage]) is an open-source documentation generator for ObjectPascal source code. It reads documentation from comments in your source code (an option to read it from an external file is also available), and generates nice docs in HTML, LaTeX or other formats. We have a console program, and a cross-platform GUI version using Lazarus.<br />
<br />
=== PasMonTray ===<br />
[http://pasmontray.sourceforge.net/ PasMonTray] is an open-source CPU and memory usage monitor that sits in the system tray. Uses [[TrayIcon]] and various Win32 api calls.<br />
<br />
=== PasViz ===<br />
[http://www.galapagossoftware.com/developer-tools/pasviz PasViz] is a developer utility for automatically generating unit dependency diagrams based on pascal source code. This project is tested on Mac OS X and Windows, and should work on Linux with very minor adjustments. Requires GraphViz (or other software that can view .dot files) for viewing the graphs.<br />
<br />
=== Project PouchHiker ===<br />
[http://www.pouchhiker.com PouchHiker] is written in Lazarus, using KOL-CE and lNet.<br />
PouchHiker lets you connect and participate in the gps-carpool network (www.gps-carpool.net).<br />
<br />
=== Project Theseus ===<br />
Tom Lisjac's [http://theseus.sourceforge.net Project Theseus] is using Lazarus and FPC for creating a rapid deployment and distribution system for Linux called [http://theseus.sourceforge.net/index.php?wiki=EpikBuilder Epik-Builder]. [http://theseus.sourceforge.net/index.php?wiki=EpikStopwatch EpikStopwatch] and [http://theseus.sourceforge.net/index.php?wiki=EpikBrowser EpikBrowser] are also Lazarus based projects that are currently under development. <br />
<br />
=== recALL ===<br />
[http://keit.co/p/recall recALL] is free and portable multifunctional password recovery and auditing solution for Windows - instantly finds and recovers passwords from more than 200 popular applications (FTP, E-mail clients, Instant Messengers, Browsers, etc) and recovering licenses from over 2800 programs. Entirely written in Free Pascal and Lazarus.<br />
<br />
=== QFront ===<br />
[http://www.ullihome.de QFront] is a platform independent frontend for the CPU Emulator QEmu<br />
<br />
=== QueryIt ===<br />
[http://www.cnblogs.com/lazarus/articles/2072143.html QueryIt] includes two functions; one is an AddressBook, another is an URL Collector. [http://images.cnblogs.com/cnblogs_com/lazarus/303383/r_screen_01.png Screen Shot-01]<br />
[http://images.cnblogs.com/cnblogs_com/lazarus/303383/r_screen_02.png Screen Shot-02]<br />
[http://images.cnblogs.com/cnblogs_com/lazarus/303383/r_screen_03.png Screen Shot-03]<br />
[http://images.cnblogs.com/cnblogs_com/lazarus/303383/r_screen_04.png Screen Shot-04]<br />
[http://images.cnblogs.com/cnblogs_com/lazarus/303383/r_screen_05.png Screen Shot-05]<br />
[http://images.cnblogs.com/cnblogs_com/lazarus/303383/r_screen_06.png Screen Shot-06]<br />
<br />
=== Seksi Commander ===<br />
[http://radekc.regnet.cz/ Seksi Commander] is a GPL File manager for Linux developed in Lazarus and Free Pascal.<br />
Integrated bin, text, hex viewer (own component) and editor based on SynEdit.<br />
<br />
=== SFS Technology ===<br />
[http://code.google.com/p/sfs-technology/ SFS-Technology] solves dependency problems on a Debian/Ubuntu/Linux Tiger operating system. <br />
<br />
=== Shell for Gammu (Mobile Phone Tool) ===<br />
The [http://www.petersieg.de/gammush Gammush Site] offers hardcopies and downloads for this<br />
application. Gammush is a shell for gammu.exe. It allows to backup/restore your phone data,<br />
get, edit, put logos, set date+time, send sms messages etc.<br />
<br />
=== Siages ===<br />
[http://siages.solis.coop.br/ Siages] is an ERP application made with Lazarus.<br />
<br />
=== SimpleGit ===<br />
<br />
[http://soft-practice.com/apps/simplegit SimpleGit] is a cross platform user interface for the popular configuration management system '''git''' for Linux, Mac and Windows. SimpleGit doesn't use any of the language of git, it just explains changes, conflicts and resolutions in simple ways with no learning curve between platforms interacting with a hub like GitHub, GitLab or Stash to make using Git easy.<br />
<br />
[[Image:win clone repository.png|320px|Clone a repo on Windows]]<br />
[[Image:linux make change.png|280px|Make a change on Linux]]<br />
[[Image:mac resolve conflict.png|280px|Resolve a conflict on Mac]]<br />
<br />
<br />
=== Sun Simulator ===<br />
The [http://www.benibela.de/tools_en.html#sunsimulator sun simulator] changes the gamma/brightness/color setting depending on the time and date. It is supposed to synchronize the color of the display to the color of the sun light outside, but before it can do that, you have to manually set your preferred color for some fixed times (e.g. noon, dawn, night). (Windows only)<br />
<br />
=== Transmission Remote GUI ===<br />
[http://code.google.com/p/transmisson-remote-gui/ Transmission Remote GUI] is a feature rich cross platform front-end to remotely control a Transmission Bit-Torrent client daemon via its RPC protocol. Transmission Remote GUI is faster and has more functionality than the build-in Transmission web interface.<br />
<br />
=== Turbo Dictionary ===<br />
[http://www.turbog.com/2012/04/18/turbo-dictionary/ Turbo Dictionary] is a It is a english to turkish dictionary. It is a GPL licensed software.<br />
<br />
=== Turbo Postman ===<br />
[http://www.turbog.com/2012/04/18/turbo-postman/ Turbo Postman] is a It is a mass mail sending tool. You can use a text formatted file or a MySQL database for mail sending list. It is a GPL licensed software.<br />
<br />
=== Turbo Talker ===<br />
[http://www.turbog.com/2012/04/18/turbo-talker/ Turbo Talker] is a Network messaging tool with DES encryption support. You can configure port number and 8 byte DES key. It is peer-to-peer application. It is licensed under GPL license.<br />
<br />
=== Ubuntu Control Center ===<br />
Ubuntu Control Center or UCC is an application inspired by Mandriva Control Center and aims to centralize and organize in a simple and intuitive form the main configuration tools for Ubuntu distribution. UCC uses all the native applications already bundled with Ubuntu, but it also utilize some third-party apps like "Hardinfo", "Boot-up Manager", "GuFW" and "Font-Manager".<br />
<br />
=== Virtual Magnifying Glass ===<br />
[http://magnifier.sourceforge.net/ Virtual Magnifying Glass] is designed for visually-impaired and others who need to magnify a part of the screen. Unlike most similar programs it does not open a separate window for the magnification but instead puts a movable magnifying glass on screen. The project was converted from Visual Studio .NET to Lazarus and now offers a Linux version. Mac OS X and Pocket PC versions are planned.<br />
<br />
=== WandS ===<br />
[http://sourceforge.net/projects/wands/ WandS] (Wake and Shutdown) is a program for webmasters or sysadmins for taking control of servers at datacenters. With WandS, you can shutdown or wake up any server or server group at any time through SSH or SMB.<br />
<br />
=== Wi(n)XtaP ===<br />
[http://www.freewebs.com/bpsoftware/ Wi(n)Xtap] (formed by the words Windows XP Vista) was a program created for early versions of Lazarus. This program allowed the creation of the .manifest file so to set up a graphical theme to your application and it allowed the user to define a customized icon. This program is useless since 0.9.24 because those features have been implemented into the IDE itself. Stable releases of Wi(n)XtaP where the 4.0 beta, 5.0, 6.0 and the latest 6.1 (fixes of 6.0). Further plans to expand its capabilities are temporally blocked.<br />
<br />
=== WikiHelp ===<br />
[http://www.ullihome.de WikiHelp] is a small tool that generates HTML pages from a Wiki. It downloads the content automatically and convert the WikiText pages into HTML. Most WikiText features are useable including images, tables and so on.<br />
<br />
=== Win32 API Manager ===<br />
The [http://www.benibela.de/tools_en.html#apim API Manager] is a very old program giving a GUI for Win32 API functions. It can do everything there is an API function for, e.g. list all processes, change their priority or kill them; list all windows and change their attributes (e.g. change a password, edit to a normal, readable edit) ... It was originally written with D4 for Win98, but I ported it to Lazarus and added support for NT-platform functions. So, it should still work nowadays.<br />
<br />
=== WindSirf ===<br />
The [http://windsurfer.me.uk WindSirf] application reads and displays files from the GTS-31 GPS. Initially it is aimed at windsurfers, but may expand its capabilities. The initial release is for Win 32 only.<br />
<br />
=== Xidel ===<br />
A platform independent [http://videlibri.sourceforge.net/xidel.html command line tool] to download webpages and extract data from them, using XPath 2 / XQuery expressions, CSS 3 selectors or custom pattern-matching templates. It is kind of an example for my [[Projects_using_Lazarus#Internet_Tools | internet tools]].<br />
<br />
'''If your Lazarus project should be listed here, please edit this page and add it!'''<br />
<br />
[[Category:Lazarus]]<br />
[[Category:Promotion]]<br />
[[Category: Software written in Free Pascal]]<br />
[[Category: Software created with Lazarus]]</div>007https://wiki.freepascal.org/index.php?title=BGRAControls&diff=111376BGRAControls2017-08-05T15:48:03Z<p>007: /* Install */</p>
<hr />
<div>{{BGRAControls}}<br />
<br />
= Install =<br />
<br />
To quickly install everything and keep up-to-date use [[Online Package Manager]]. Under Linux you need to have installed libxtst-dev and libgl-dev to install BGRAControls.<br />
<br />
=== Download BGRABitmap ===<br />
<br />
Install BGRABitmap with the file bgrabitmappack.lpk.<br />
<br />
GitHub: https://github.com/bgrabitmap/bgrabitmap/<br />
<br />
=== Download BGRAControls ===<br />
<br />
Install BGRAControls with the file bgracontrols.lpk.<br />
<br />
GitHub: https://github.com/bgrabitmap/bgracontrols/<br />
<br />
= BGRA Controls =<br />
<br />
BGRA Controls is a set of graphical UI elements that you can use with Lazarus LCL applications.<br />
Under Linux you need to have installed libxtst-dev and libgl-dev.<br />
<br />
=== TBCButton ===<br />
<br />
[[Image:bcbutton.png]]<br />
<br />
A button control that can be styled through properties for each state like StateClicked, StateHover, StateNormal with settings like gradients, border and text with shadows. You can assign an already made style through the property AssignStyle.<br />
<br />
=== TBCButtonFocus ===<br />
<br />
Like TBCButton but it supports focus like normal TButton.<br />
<br />
=== TBCGameGrid ===<br />
<br />
[[Image:bcgamegrid.png]]<br />
<br />
A grid with custom width and height of items and any number of horizontal and vertical cells that can be drawn with BGRABitmap directly with the OnRenderControl event.<br />
<br />
=== TBCImageButton ===<br />
<br />
[[Image:samplebgraimagebutton.png]]<br />
<br />
[[Image:samplebgraimagebuttonalpha.png]]<br />
<br />
A button control that can be styled with one image file, containing the drawing for each state Normal, Hovered, Active and Disabled. It supports 9-slice scaling feature. It supports a nice fading animation that can be turned on.<br />
<br />
=== TBCXButton ===<br />
<br />
[[Image:bcxbutton.png]]<br />
<br />
A button control that can be styled by code with the OnRenderControl event. Or even better create your own child control inheriting from this class.<br />
<br />
=== TBCLabel ===<br />
<br />
[[Image:bclabel.png]]<br />
<br />
A label control that can be styled through properties, it supports shadow, custom borders and background.<br />
<br />
=== TBCMaterialDesignButton ===<br />
<br />
A button control that has an animation effect according to Google Material Design guidelines. It supports custom color for background and for the circle animation, also you can customize the shadow.<br />
<br />
=== TBCPanel ===<br />
<br />
[[Image:bcpanel.png]]<br />
<br />
A panel control that can be styled through properties. You can assign an already made style through the property AssignStyle.<br />
<br />
=== TBCRadialProgressBar ===<br />
<br />
A progress bar with radial style. You can set the color and text properties as you like.<br />
<br />
=== TBCToolBar ===<br />
<br />
A TToolBar with an event OnRedraw to paint it using BGRABitmap. It supports also the default OnPaintButton to customize the buttons drawing. By default it comes with a Windows 7 like explorer toolbar style.<br />
<br />
=== TBCTrackBarUpdown ===<br />
<br />
A control to input numeric values with works like a trackbar and a spinedit both in one control.<br />
<br />
=== TBGRAFlashProgressBar ===<br />
<br />
[[Image:BC-Bgraflashprogressbar.png]]<br />
<br />
A progress bar with a default style inspired in the old Flash Player Setup for Windows progress dialog. You can change the color property to have different styles and also you can use the event OnRedraw to paint custom styles on it like text or override the entire default drawing.<br />
<br />
=== TBGRAGraphicControl ===<br />
<br />
Is like a paintbox. You can draw with transparency with this control using the OnRedraw event.<br />
<br />
=== TBGRAImageList ===<br />
<br />
[[Image:before-TImageList.png]]<br />
<br />
[[Image:after-TBGRAImageList.png]]<br />
<br />
An image list that supports alpha in all supported platforms.<br />
<br />
=== TBGRAImageManipulation ===<br />
<br />
[[Image:bgraimagemanipulation.jpg]]<br />
<br />
A tool to manipulate pictures, see the demo that shows all the capability that comes with it.<br />
<br />
=== TBGRAKnob ===<br />
<br />
[[Image:BC-Bgraknob.png]]<br />
<br />
A knob that can be styled through properties.<br />
<br />
=== TBGRAResizeSpeedButton ===<br />
<br />
A speed button that can resize the glyph to fit in the entire control.<br />
<br />
=== TBGRAShape ===<br />
<br />
[[Image:samplebgrashape.png]]<br />
<br />
A control with configurable shapes like polygon and ellipse that can be filled with gradients and can have custom borders and many other visual settings.<br />
<br />
=== TBGRASpeedButton ===<br />
<br />
[[Image:BGRASpeedButton.png]]<br />
<br />
A speed button that in GTK and GTK2 provides BGRABitmap powered transparency to the glyph.<br />
<br />
=== TBGRASpriteAnimation ===<br />
<br />
[[Image:bgraspriteanimation.png]]<br />
<br />
A component that can be used as image viewer or animation viewer, supports the loading of gif files.<br />
<br />
=== TBGRAVirtualScreen ===<br />
<br />
Is like a panel. You can draw this control using the OnRedraw event.<br />
<br />
=== TDTAnalogClock ===<br />
<br />
A clock.<br />
<br />
=== TDTAnalogGaugue ===<br />
<br />
A gauge.<br />
<br />
=== TDTThemedClock ===<br />
<br />
Another clock.<br />
<br />
=== TDTThemedGauge ===<br />
<br />
Another gauge.<br />
<br />
=== TPSImport_BGRAPascalScript ===<br />
<br />
A component to load BGRABitmap pascal script utilities.<br />
<br />
= BGRA Custom Drawn =<br />
<br />
BGRA Custom Drawn is a set of controls inherited from Custom Drawn. These come with a default dark style that is like Photoshop.<br />
<br />
=== TBCDButton ===<br />
<br />
A button control that is styled with TBGRADrawer.<br />
<br />
=== TBCDEdit ===<br />
<br />
An edit control that is styled with TBGRADrawer.<br />
<br />
=== TBCDStaticText ===<br />
<br />
A label control that is styled with TBGRADrawer.<br />
<br />
=== TBCDProgressBar ===<br />
<br />
A progress bar control that is styled with TBGRADrawer.<br />
<br />
=== TBCDSpinEdit ===<br />
<br />
A spin edit control that is styled with TBGRADrawer.<br />
<br />
=== TBCDCheckBox ===<br />
<br />
A check box control that is styled with TBGRADrawer.<br />
<br />
=== TBCRadioButton ===<br />
<br />
A radio button that is styled with TBGRADrawer.<br />
<br />
= Sample code =<br />
<br />
BGRA Controls comes with nice demos to show how to use the stuff and extra things you can use in your own projects.<br />
<br />
=== Pascal Script Library ===<br />
<br />
Putting BGRABitmap methods into a .dll with c#, java and pascal headers.<br />
<br />
=== BGRA Ribbon Custom ===<br />
<br />
How to create a fully themed window using the controls to achieve a Ribbon like application.<br />
<br />
=== Tests ===<br />
<br />
There are test for analog controls (clock and gauge), BC prefixed controls, BGRA prefixed controls, BGRA Custom Drawn controls, how to use Pascal Script and BGRABitmap, bgrascript or how to create your own scripting solution with BGRABitmap.<br />
<br />
=== Tests Extra ===<br />
<br />
[[Image:game_maze.png]]<br />
<br />
[[Image:game_puzzle.png]]<br />
<br />
[[Image:customdrawnwindows7.png]]<br />
<br />
[[File:slicescaledtachart.png]]<br />
<br />
These are extra tests like how to use fading effect, an fpGUI theme, games like maze and puzzle, how we created the material design animation, pix2svg or how to convert a small picture to svg using hexagons, rectangles and ellipses, plugins or how to load .dlls and use into a TBGRAVirtualScreen, rain effect, shadow effect, 9-slice-scaling with Custom Drawn or how to theme with bitmaps an application to look like Windows themes and 9-slice-scaling with charts.<br />
<br />
= Another units =<br />
<br />
These units come with BGRA Controls and contains more functionality that is sometimes used with the controls, sometimes not but are usefull in some way. Some are listed here, others you can see linked directly with any control like bcrtti, bcstylesform, bctools and bctypes.<br />
<br />
=== BCEffect ===<br />
<br />
Fading effect with BGRABitmap.<br />
<br />
=== BCFilters ===<br />
<br />
A set of pixel filters to use with BGRABitmap.<br />
<br />
=== BGRAScript ===<br />
<br />
Scripting with BGRABitmap, see test project.<br />
<br />
= Related Articles =<br />
<br />
[[BGRASpriteAnimation]] - Usage of the sprite animation component.<br />
<br />
[[uE_Controls]] - Other controls developed with BGRABitmap.<br />
<br />
[[BGRABitmap]] - The library used to create this controls.<br />
<br />
[[LazPaint]] - A paint program developed with Lazarus and BGRABitmap.<br />
<br />
[[Category:Components]]<br />
[[Category:Graphics]]<br />
[[Category:BGRAControls]]</div>007https://wiki.freepascal.org/index.php?title=BGRAControls&diff=111375BGRAControls2017-08-05T15:47:19Z<p>007: /* Install */</p>
<hr />
<div>{{BGRAControls}}<br />
<br />
= Install =<br />
<br />
To quickly install everything and keep up-to-date use [[Online Package Manager]].<br />
<br />
=== Download BGRABitmap ===<br />
<br />
Install BGRABitmap with the file bgrabitmappack.lpk.<br />
<br />
GitHub: https://github.com/bgrabitmap/bgrabitmap/<br />
<br />
=== Download BGRAControls ===<br />
<br />
Install BGRAControls with the file bgracontrols.lpk.<br />
<br />
GitHub: https://github.com/bgrabitmap/bgracontrols/<br />
<br />
= BGRA Controls =<br />
<br />
BGRA Controls is a set of graphical UI elements that you can use with Lazarus LCL applications.<br />
Under Linux you need to have installed libxtst-dev and libgl-dev.<br />
<br />
=== TBCButton ===<br />
<br />
[[Image:bcbutton.png]]<br />
<br />
A button control that can be styled through properties for each state like StateClicked, StateHover, StateNormal with settings like gradients, border and text with shadows. You can assign an already made style through the property AssignStyle.<br />
<br />
=== TBCButtonFocus ===<br />
<br />
Like TBCButton but it supports focus like normal TButton.<br />
<br />
=== TBCGameGrid ===<br />
<br />
[[Image:bcgamegrid.png]]<br />
<br />
A grid with custom width and height of items and any number of horizontal and vertical cells that can be drawn with BGRABitmap directly with the OnRenderControl event.<br />
<br />
=== TBCImageButton ===<br />
<br />
[[Image:samplebgraimagebutton.png]]<br />
<br />
[[Image:samplebgraimagebuttonalpha.png]]<br />
<br />
A button control that can be styled with one image file, containing the drawing for each state Normal, Hovered, Active and Disabled. It supports 9-slice scaling feature. It supports a nice fading animation that can be turned on.<br />
<br />
=== TBCXButton ===<br />
<br />
[[Image:bcxbutton.png]]<br />
<br />
A button control that can be styled by code with the OnRenderControl event. Or even better create your own child control inheriting from this class.<br />
<br />
=== TBCLabel ===<br />
<br />
[[Image:bclabel.png]]<br />
<br />
A label control that can be styled through properties, it supports shadow, custom borders and background.<br />
<br />
=== TBCMaterialDesignButton ===<br />
<br />
A button control that has an animation effect according to Google Material Design guidelines. It supports custom color for background and for the circle animation, also you can customize the shadow.<br />
<br />
=== TBCPanel ===<br />
<br />
[[Image:bcpanel.png]]<br />
<br />
A panel control that can be styled through properties. You can assign an already made style through the property AssignStyle.<br />
<br />
=== TBCRadialProgressBar ===<br />
<br />
A progress bar with radial style. You can set the color and text properties as you like.<br />
<br />
=== TBCToolBar ===<br />
<br />
A TToolBar with an event OnRedraw to paint it using BGRABitmap. It supports also the default OnPaintButton to customize the buttons drawing. By default it comes with a Windows 7 like explorer toolbar style.<br />
<br />
=== TBCTrackBarUpdown ===<br />
<br />
A control to input numeric values with works like a trackbar and a spinedit both in one control.<br />
<br />
=== TBGRAFlashProgressBar ===<br />
<br />
[[Image:BC-Bgraflashprogressbar.png]]<br />
<br />
A progress bar with a default style inspired in the old Flash Player Setup for Windows progress dialog. You can change the color property to have different styles and also you can use the event OnRedraw to paint custom styles on it like text or override the entire default drawing.<br />
<br />
=== TBGRAGraphicControl ===<br />
<br />
Is like a paintbox. You can draw with transparency with this control using the OnRedraw event.<br />
<br />
=== TBGRAImageList ===<br />
<br />
[[Image:before-TImageList.png]]<br />
<br />
[[Image:after-TBGRAImageList.png]]<br />
<br />
An image list that supports alpha in all supported platforms.<br />
<br />
=== TBGRAImageManipulation ===<br />
<br />
[[Image:bgraimagemanipulation.jpg]]<br />
<br />
A tool to manipulate pictures, see the demo that shows all the capability that comes with it.<br />
<br />
=== TBGRAKnob ===<br />
<br />
[[Image:BC-Bgraknob.png]]<br />
<br />
A knob that can be styled through properties.<br />
<br />
=== TBGRAResizeSpeedButton ===<br />
<br />
A speed button that can resize the glyph to fit in the entire control.<br />
<br />
=== TBGRAShape ===<br />
<br />
[[Image:samplebgrashape.png]]<br />
<br />
A control with configurable shapes like polygon and ellipse that can be filled with gradients and can have custom borders and many other visual settings.<br />
<br />
=== TBGRASpeedButton ===<br />
<br />
[[Image:BGRASpeedButton.png]]<br />
<br />
A speed button that in GTK and GTK2 provides BGRABitmap powered transparency to the glyph.<br />
<br />
=== TBGRASpriteAnimation ===<br />
<br />
[[Image:bgraspriteanimation.png]]<br />
<br />
A component that can be used as image viewer or animation viewer, supports the loading of gif files.<br />
<br />
=== TBGRAVirtualScreen ===<br />
<br />
Is like a panel. You can draw this control using the OnRedraw event.<br />
<br />
=== TDTAnalogClock ===<br />
<br />
A clock.<br />
<br />
=== TDTAnalogGaugue ===<br />
<br />
A gauge.<br />
<br />
=== TDTThemedClock ===<br />
<br />
Another clock.<br />
<br />
=== TDTThemedGauge ===<br />
<br />
Another gauge.<br />
<br />
=== TPSImport_BGRAPascalScript ===<br />
<br />
A component to load BGRABitmap pascal script utilities.<br />
<br />
= BGRA Custom Drawn =<br />
<br />
BGRA Custom Drawn is a set of controls inherited from Custom Drawn. These come with a default dark style that is like Photoshop.<br />
<br />
=== TBCDButton ===<br />
<br />
A button control that is styled with TBGRADrawer.<br />
<br />
=== TBCDEdit ===<br />
<br />
An edit control that is styled with TBGRADrawer.<br />
<br />
=== TBCDStaticText ===<br />
<br />
A label control that is styled with TBGRADrawer.<br />
<br />
=== TBCDProgressBar ===<br />
<br />
A progress bar control that is styled with TBGRADrawer.<br />
<br />
=== TBCDSpinEdit ===<br />
<br />
A spin edit control that is styled with TBGRADrawer.<br />
<br />
=== TBCDCheckBox ===<br />
<br />
A check box control that is styled with TBGRADrawer.<br />
<br />
=== TBCRadioButton ===<br />
<br />
A radio button that is styled with TBGRADrawer.<br />
<br />
= Sample code =<br />
<br />
BGRA Controls comes with nice demos to show how to use the stuff and extra things you can use in your own projects.<br />
<br />
=== Pascal Script Library ===<br />
<br />
Putting BGRABitmap methods into a .dll with c#, java and pascal headers.<br />
<br />
=== BGRA Ribbon Custom ===<br />
<br />
How to create a fully themed window using the controls to achieve a Ribbon like application.<br />
<br />
=== Tests ===<br />
<br />
There are test for analog controls (clock and gauge), BC prefixed controls, BGRA prefixed controls, BGRA Custom Drawn controls, how to use Pascal Script and BGRABitmap, bgrascript or how to create your own scripting solution with BGRABitmap.<br />
<br />
=== Tests Extra ===<br />
<br />
[[Image:game_maze.png]]<br />
<br />
[[Image:game_puzzle.png]]<br />
<br />
[[Image:customdrawnwindows7.png]]<br />
<br />
[[File:slicescaledtachart.png]]<br />
<br />
These are extra tests like how to use fading effect, an fpGUI theme, games like maze and puzzle, how we created the material design animation, pix2svg or how to convert a small picture to svg using hexagons, rectangles and ellipses, plugins or how to load .dlls and use into a TBGRAVirtualScreen, rain effect, shadow effect, 9-slice-scaling with Custom Drawn or how to theme with bitmaps an application to look like Windows themes and 9-slice-scaling with charts.<br />
<br />
= Another units =<br />
<br />
These units come with BGRA Controls and contains more functionality that is sometimes used with the controls, sometimes not but are usefull in some way. Some are listed here, others you can see linked directly with any control like bcrtti, bcstylesform, bctools and bctypes.<br />
<br />
=== BCEffect ===<br />
<br />
Fading effect with BGRABitmap.<br />
<br />
=== BCFilters ===<br />
<br />
A set of pixel filters to use with BGRABitmap.<br />
<br />
=== BGRAScript ===<br />
<br />
Scripting with BGRABitmap, see test project.<br />
<br />
= Related Articles =<br />
<br />
[[BGRASpriteAnimation]] - Usage of the sprite animation component.<br />
<br />
[[uE_Controls]] - Other controls developed with BGRABitmap.<br />
<br />
[[BGRABitmap]] - The library used to create this controls.<br />
<br />
[[LazPaint]] - A paint program developed with Lazarus and BGRABitmap.<br />
<br />
[[Category:Components]]<br />
[[Category:Graphics]]<br />
[[Category:BGRAControls]]</div>007