2021-06-25 13:54:01 -06:00
using System.Drawing ;
using System.Runtime.InteropServices ;
2025-08-18 13:56:47 -05:00
using System.Reflection ;
using System.Threading.Tasks ;
2021-06-25 13:54:01 -06:00
2024-02-23 11:49:54 +01:00
namespace Photino.NET ;
2022-09-14 12:39:23 -05:00
public partial class PhotinoWindow
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
//PRIVATE FIELDS
2023-07-07 22:44:17 +02:00
/// <summary>
/// Parameters sent to Photino.Native to start a new instance of a Photino.Native window.
/// </summary>
/// <param name="Resizable">Indicates whether the window is resizable.</param>
/// <param name="ContextMenuEnabled">Specifies whether the context menu is enabled.</param>
2025-03-11 11:55:06 +01:00
/// <param name="ZoomEnabled">Specifies whether the user zoom is enabled.</param>
2023-07-07 22:44:17 +02:00
/// <param name="CustomSchemeNames">An array of strings representing custom scheme names.</param>
/// <param name="DevToolsEnabled">Specifies whether developer tools are enabled.</param>
/// <param name="GrantBrowserPermissions">Indicates whether browser permissions are granted.</param>
/// <param name="TemporaryFilesPath">Defines the path for temporary files.</param>
/// <param name="Title">Sets the title of the window.</param>
/// <param name="UseOsDefaultLocation">Specifies whether the window should use the OS default location.</param>
/// <param name="UseOsDefaultSize">Indicates whether the window should use the OS default size.</param>
/// <param name="Zoom">Sets the zoom level for the window.</param>
2022-09-14 12:39:23 -05:00
private PhotinoNativeParameters _startupParameters = new ( )
{
Resizable = true , //These values can't be initialized within the struct itself. Set required defaults.
ContextMenuEnabled = true ,
2025-03-11 11:55:06 +01:00
ZoomEnabled = true ,
2022-09-14 12:39:23 -05:00
CustomSchemeNames = new string [ 16 ] ,
DevToolsEnabled = true ,
GrantBrowserPermissions = true ,
2023-09-14 12:24:07 -05:00
UserAgent = "Photino WebView" ,
MediaAutoplayEnabled = true ,
FileSystemAccessEnabled = true ,
WebSecurityEnabled = true ,
JavascriptClipboardAccessEnabled = true ,
MediaStreamEnabled = true ,
SmoothScrollingEnabled = true ,
2024-01-04 10:58:18 -07:00
IgnoreCertificateErrorsEnabled = false ,
2024-10-17 13:46:43 -06:00
NotificationsEnabled = true ,
2024-08-30 11:38:25 -06:00
TemporaryFilesPath = IsWindowsPlatform
2022-09-14 12:39:23 -05:00
? Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . LocalApplicationData ) , "Photino" )
: null ,
Title = "Photino" ,
UseOsDefaultLocation = true ,
UseOsDefaultSize = true ,
Zoom = 100 ,
2023-08-24 12:19:10 -06:00
MaxHeight = int . MaxValue ,
MaxWidth = int . MaxValue ,
2022-09-14 12:39:23 -05:00
} ;
//Pointers to the type and instance.
private static IntPtr _nativeType = IntPtr . Zero ;
private IntPtr _nativeInstance ;
private readonly int _managedThreadId ;
//There can only be 1 message loop for all windows.
private static bool _messageLoopIsStarted = false ;
//READ ONLY PROPERTIES
2023-07-07 22:44:17 +02:00
/// <summary>
/// Indicates whether the current platform is Windows.
/// </summary>
/// <value>
/// <c>true</c> if the current platform is Windows; otherwise, <c>false</c>.
/// </value>
2022-09-14 12:39:23 -05:00
public static bool IsWindowsPlatform = > RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ;
2023-08-24 12:19:10 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Indicates whether the current platform is MacOS.
/// </summary>
/// <value>
/// <c>true</c> if the current platform is MacOS; otherwise, <c>false</c>.
/// </value>
2022-09-14 12:39:23 -05:00
public static bool IsMacOsPlatform = > RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) ;
2023-08-24 12:19:10 -06:00
2023-10-26 10:27:18 -05:00
/// <summary>
/// Indicates the version of MacOS
/// </summary>
public static Version MacOsVersion = > IsMacOsPlatform ? Version . Parse ( RuntimeInformation . OSDescription . Split ( ' ' ) [ 1 ] ) : null ;
2023-07-07 22:44:17 +02:00
/// <summary>
/// Indicates whether the current platform is Linux.
/// </summary>
/// <value>
/// <c>true</c> if the current platform is Linux; otherwise, <c>false</c>.
/// </value>
2022-09-14 12:39:23 -05:00
public static bool IsLinuxPlatform = > RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) ;
2023-07-07 22:44:17 +02:00
/// <summary>
/// Represents a property that gets the handle of the native window on a Windows platform.
/// </summary>
/// <remarks>
/// Only available on the Windows platform.
/// If this property is accessed from a non-Windows platform, a PlatformNotSupportedException will be thrown.
/// If this property is accessed before the window is initialized, an ApplicationException will be thrown.
/// </remarks>
/// <value>
/// The handle of the native window. The value is of type <see cref="IntPtr"/>.
/// </value>
/// <exception cref="System.ApplicationException">Thrown when the window is not initialized yet.</exception>
/// <exception cref="System.PlatformNotSupportedException">Thrown when accessed from a non-Windows platform.</exception>
2022-09-14 12:39:23 -05:00
public IntPtr WindowHandle
{
get
{
if ( IsWindowsPlatform )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
throw new ApplicationException ( "The Photino window is not initialized yet" ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var handle = IntPtr . Zero ;
Invoke ( ( ) = > handle = Photino_getHwnd_win32 ( _nativeInstance ) ) ;
return handle ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
else
throw new PlatformNotSupportedException ( $"{nameof(WindowHandle)} is only supported on Windows." ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets list of information for each monitor from the native window.
/// This property represents a list of Monitor objects associated to each display monitor.
/// </summary>
/// <remarks>
/// If called when the native instance of the window is not initialized, it will throw an ApplicationException.
/// </remarks>
/// <exception cref="ApplicationException">Thrown when the native instance of the window is not initialized.</exception>
/// <returns>
/// A read-only list of Monitor objects representing information about each display monitor.
/// </returns>
2022-09-14 12:39:23 -05:00
public IReadOnlyList < Monitor > Monitors
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
throw new ApplicationException ( "The Photino window hasn't been initialized yet." ) ;
2021-06-25 13:54:01 -06:00
2024-09-20 16:23:01 -06:00
List < Monitor > monitors = new ( ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
int callback ( in NativeMonitor monitor )
{
monitors . Add ( new Monitor ( monitor ) ) ;
return 1 ;
}
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
Invoke ( ( ) = > Photino_GetAllMonitors ( _nativeInstance , callback ) ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
return monitors ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Retrieves the primary monitor information from the native window instance.
/// </summary>
/// <exception cref="ApplicationException"> Thrown when the window hasn't been initialized yet. </exception>
/// <returns>
/// Returns a Monitor object representing the main monitor. The main monitor is the first monitor in the list of available monitors.
/// </returns>
2022-09-14 12:39:23 -05:00
public Monitor MainMonitor
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
throw new ApplicationException ( "The Photino window hasn't been initialized yet." ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
return Monitors [ 0 ] ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets the dots per inch (DPI) for the primary display from the native window.
/// </summary>
/// <exception cref="ApplicationException">
/// An ApplicationException is thrown if the window hasn't been initialized yet.
/// </exception>
2022-09-14 12:39:23 -05:00
public uint ScreenDpi
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
throw new ApplicationException ( "The Photino window hasn't been initialized yet." ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
uint dpi = 0 ;
Invoke ( ( ) = > dpi = Photino_GetScreenDpi ( _nativeInstance ) ) ;
return dpi ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets a unique GUID to identify the native window.
/// </summary>
/// <remarks>
/// This property is not currently utilized by the Photino framework.
/// </remarks>
2022-09-14 12:39:23 -05:00
public Guid Id { get ; } = Guid . NewGuid ( ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
//READ-WRITE PROPERTIES
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true, the native window will appear centered on the screen. By default, this is set to false.
/// </summary>
/// <exception cref="ApplicationException">
/// Thrown if trying to set value after native window is initalized.
/// </exception>
2022-09-14 12:39:23 -05:00
public bool Centered
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . CenterOnInitialize ;
return false ;
}
set
{
if ( _nativeInstance = = IntPtr . Zero )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _startupParameters . CenterOnInitialize ! = value )
_startupParameters . CenterOnInitialize = value ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
else
Invoke ( ( ) = > Photino_Center ( _nativeInstance ) ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets a value indicating whether the native window should be chromeless.
/// When true, the native window will appear without a title bar or border.
/// By default, this is set to false.
/// </summary>
/// <exception cref="ApplicationException">
/// Thrown if trying to set value after native window is initalized.
/// </exception>
/// <remarks>
/// The user has to supply titlebar, border, dragging and resizing manually.
/// </remarks>
2022-09-14 12:39:23 -05:00
public bool Chromeless
{
get
{
return _startupParameters . Chromeless ;
}
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _startupParameters . Chromeless ! = value )
_startupParameters . Chromeless = value ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
else
throw new ApplicationException ( "Chromeless can only be set before the native window is instantiated." ) ;
}
}
2024-05-08 21:10:53 +03:00
/// <summary>
2024-05-30 09:04:45 -06:00
/// When true, the native window and browser control can be displayed with transparent background.
/// Html document's body background must have alpha-based value.
/// WebView2 on Windows can only be fully transparent or fully opaque.
2024-05-08 21:10:53 +03:00
/// By default, this is set to false.
/// </summary>
2024-05-30 09:04:45 -06:00
/// <exception cref="ApplicationException">
/// On Windows, thrown if trying to set value after native window is initalized.
/// </exception>
2024-05-08 21:10:53 +03:00
public bool Transparent
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . Transparent ;
var enabled = false ;
Invoke ( ( ) = > Photino_GetTransparentEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( Transparent ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . Transparent = value ;
else
2024-05-30 09:04:45 -06:00
{
if ( IsWindowsPlatform )
throw new ApplicationException ( "Transparent can only be set on Windows before the native window is instantiated." ) ;
else
2024-06-14 14:14:01 -06:00
{
Log ( $"Invoking Photino_SetTransparentEnabled({value})" ) ;
2024-05-30 09:04:45 -06:00
Invoke ( ( ) = > Photino_SetTransparentEnabled ( _nativeInstance , value ) ) ;
2024-06-14 14:14:01 -06:00
}
2024-05-30 09:04:45 -06:00
}
2024-05-08 21:10:53 +03:00
}
}
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true, the user can access the browser control's context menu.
/// By default, this is set to true.
/// </summary>
2022-09-14 12:39:23 -05:00
public bool ContextMenuEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . ContextMenuEnabled ;
var enabled = false ;
Invoke ( ( ) = > Photino_GetContextMenuEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( ContextMenuEnabled ! = value )
2021-06-25 13:54:01 -06:00
{
if ( _nativeInstance = = IntPtr . Zero )
2022-09-14 12:39:23 -05:00
_startupParameters . ContextMenuEnabled = value ;
2021-06-25 13:54:01 -06:00
else
2022-09-14 12:39:23 -05:00
Invoke ( ( ) = > Photino_SetContextMenuEnabled ( _nativeInstance , value ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2025-03-11 11:55:06 +01:00
/// <summary>
/// When true, the user can zoom.
/// By default, this is set to true.
/// </summary>
public bool ZoomEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . ZoomEnabled ;
var enabled = false ;
Invoke ( ( ) = > Photino_GetZoomEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( ZoomEnabled ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . ZoomEnabled = value ;
else
Invoke ( ( ) = > Photino_SetZoomEnabled ( _nativeInstance , value ) ) ;
}
}
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true, the user can access the browser control's developer tools.
/// By default, this is set to true.
/// </summary>
2022-09-14 12:39:23 -05:00
public bool DevToolsEnabled
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . DevToolsEnabled ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var enabled = false ;
Invoke ( ( ) = > Photino_GetDevToolsEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( DevToolsEnabled ! = value )
2021-06-25 13:54:01 -06:00
{
if ( _nativeInstance = = IntPtr . Zero )
2022-09-14 12:39:23 -05:00
_startupParameters . DevToolsEnabled = value ;
else
Invoke ( ( ) = > Photino_SetDevToolsEnabled ( _nativeInstance , value ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-09-14 12:24:07 -05:00
public bool MediaAutoplayEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . MediaAutoplayEnabled ;
2023-09-14 14:41:52 -06:00
2023-09-14 12:24:07 -05:00
var enabled = false ;
Invoke ( ( ) = > Photino_GetMediaAutoplayEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( MediaAutoplayEnabled ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . MediaAutoplayEnabled = value ;
else
2023-09-14 14:41:52 -06:00
throw new ApplicationException ( "MediaAutoplayEnabled can only be set before the native window is instantiated." ) ;
2023-09-14 12:24:07 -05:00
}
}
}
public string UserAgent
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
2024-08-30 11:38:25 -06:00
return _startupParameters . UserAgent ;
2023-09-14 14:41:52 -06:00
2023-09-14 12:24:07 -05:00
var userAgent = string . Empty ;
2023-09-14 14:41:52 -06:00
Invoke ( ( ) = >
{
var ptr = Photino_GetUserAgent ( _nativeInstance ) ;
userAgent = Marshal . PtrToStringAuto ( ptr ) ;
} ) ;
2023-09-14 12:24:07 -05:00
return userAgent ;
}
set
{
if ( UserAgent ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
2024-08-30 11:38:25 -06:00
_startupParameters . UserAgent = value ;
2023-09-14 12:24:07 -05:00
else
2023-09-14 14:41:52 -06:00
throw new ApplicationException ( "UserAgent can only be set before the native window is instantiated." ) ;
2023-09-14 12:24:07 -05:00
}
}
}
public bool FileSystemAccessEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . FileSystemAccessEnabled ;
2023-09-14 14:41:52 -06:00
2023-09-14 12:24:07 -05:00
var enabled = false ;
Invoke ( ( ) = > Photino_GetFileSystemAccessEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( FileSystemAccessEnabled ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . FileSystemAccessEnabled = value ;
else
2023-09-14 14:41:52 -06:00
throw new ApplicationException ( "FileSystemAccessEnabled can only be set before the native window is instantiated." ) ;
2023-09-14 12:24:07 -05:00
}
}
}
public bool WebSecurityEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . WebSecurityEnabled ;
2023-09-14 14:41:52 -06:00
2023-09-14 12:24:07 -05:00
var enabled = true ;
Invoke ( ( ) = > Photino_GetWebSecurityEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( WebSecurityEnabled ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . WebSecurityEnabled = value ;
else
2023-09-14 14:41:52 -06:00
throw new ApplicationException ( "WebSecurityEnabled can only be set before the native window is instantiated." ) ;
2023-09-14 12:24:07 -05:00
}
}
}
public bool JavascriptClipboardAccessEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . JavascriptClipboardAccessEnabled ;
2023-09-14 14:41:52 -06:00
2023-09-14 12:24:07 -05:00
var enabled = true ;
Invoke ( ( ) = > Photino_GetJavascriptClipboardAccessEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( JavascriptClipboardAccessEnabled ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . JavascriptClipboardAccessEnabled = value ;
else
2023-09-14 14:41:52 -06:00
throw new ApplicationException ( "JavascriptClipboardAccessEnabled can only be set before the native window is instantiated." ) ;
2023-09-14 12:24:07 -05:00
}
}
}
public bool MediaStreamEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . MediaStreamEnabled ;
2023-09-14 14:41:52 -06:00
2023-09-14 12:24:07 -05:00
var enabled = true ;
Invoke ( ( ) = > Photino_GetMediaStreamEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( MediaStreamEnabled ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . MediaStreamEnabled = value ;
else
2023-09-14 14:41:52 -06:00
throw new ApplicationException ( "MediaStreamEnabled can only be set before the native window is instantiated." ) ;
2023-09-14 12:24:07 -05:00
}
}
}
public bool SmoothScrollingEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . SmoothScrollingEnabled ;
2023-09-14 14:41:52 -06:00
2023-09-14 12:24:07 -05:00
var enabled = false ;
Invoke ( ( ) = > Photino_GetSmoothScrollingEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( SmoothScrollingEnabled ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . SmoothScrollingEnabled = value ;
else
2023-09-14 14:41:52 -06:00
throw new ApplicationException ( "SmoothScrollingEnabled can only be set before the native window is instantiated." ) ;
2023-09-14 12:24:07 -05:00
}
}
}
2024-01-04 10:58:18 -07:00
public bool IgnoreCertificateErrorsEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . IgnoreCertificateErrorsEnabled ;
var enabled = false ;
Invoke ( ( ) = > Photino_GetIgnoreCertificateErrorsEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( IgnoreCertificateErrorsEnabled ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . IgnoreCertificateErrorsEnabled = value ;
else
throw new ApplicationException ( "IgnoreCertificateErrorsEnabled can only be set before the native window is instantiated." ) ;
}
}
}
2024-10-17 13:46:43 -06:00
public bool NotificationsEnabled
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . NotificationsEnabled ;
var enabled = false ;
Invoke ( ( ) = > Photino_GetNotificationsEnabled ( _nativeInstance , out enabled ) ) ;
return enabled ;
}
set
{
if ( NotificationsEnabled ! = value )
{
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . NotificationsEnabled = value ;
else
throw new ApplicationException ( "NotificationsEnabled can only be set before the native window is instantiated." ) ;
}
}
}
2023-09-14 12:24:07 -05:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// This property returns or sets the fullscreen status of the window.
/// When set to true, the native window will cover the entire screen, similar to kiosk mode.
/// By default, this is set to false.
/// </summary>
2022-09-14 12:39:23 -05:00
public bool FullScreen
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . FullScreen ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var fullScreen = false ;
Invoke ( ( ) = > Photino_GetFullScreen ( _nativeInstance , out fullScreen ) ) ;
return fullScreen ;
}
set
{
if ( FullScreen ! = value )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . FullScreen = value ;
else
Invoke ( ( ) = > Photino_SetFullScreen ( _nativeInstance , value ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
///<summary>
/// Gets or Sets whether the native browser control grants all requests for access to local resources
/// such as the users camera and microphone. By default, this is set to true.
/// </summary>
/// <remarks>
/// This only works on Windows.
/// </remarks>
2022-09-14 12:39:23 -05:00
public bool GrantBrowserPermissions
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . GrantBrowserPermissions ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var grant = false ;
Invoke ( ( ) = > Photino_GetGrantBrowserPermissions ( _nativeInstance , out grant ) ) ;
return grant ;
}
set
{
if ( GrantBrowserPermissions ! = value )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . GrantBrowserPermissions = value ;
else
2023-09-14 14:41:52 -06:00
throw new ApplicationException ( "GrantBrowserPermissions can only be set before the native window is instantiated." ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// /// <summary>
/// Gets or Sets the Height property of the native window in pixels.
/// Default value is 0.
/// </summary>
/// <seealso cref="UseOsDefaultSize" />
2022-09-14 12:39:23 -05:00
public int Height
{
get = > Size . Height ;
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
var currentSize = Size ;
if ( currentSize . Height ! = value )
Size = new Size ( currentSize . Width , value ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
private string _iconFile ;
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the icon file for the native window title bar.
/// The file must be located on the local machine and cannot be a URL. The default is none.
/// </summary>
/// <remarks>
/// This only works on Windows and Linux.
/// </remarks>
/// <value>
/// The file path to the icon.
/// </value>
/// <exception cref="System.ArgumentException">Icon file: {value} does not exist.</exception>
2022-09-14 12:39:23 -05:00
public string IconFile
{
get = > _iconFile ;
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _iconFile ! = value )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( ! File . Exists ( value ) )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
var absolutePath = $"{System.AppContext.BaseDirectory}{value}" ;
if ( ! File . Exists ( absolutePath ) )
throw new ArgumentException ( $"Icon file: {value} does not exist." ) ;
}
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
_iconFile = value ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
2024-08-30 11:38:25 -06:00
_startupParameters . WindowIconFile = _iconFile ;
2022-09-14 12:39:23 -05:00
else
Invoke ( ( ) = > Photino_SetIconFile ( _nativeInstance , _iconFile ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the native window Left (X) and Top coordinates (Y) in pixels.
/// Default is 0,0 which means the window will be aligned to the top left edge of the screen.
/// </summary>
/// <seealso cref="UseOsDefaultLocation" />
2022-09-14 12:39:23 -05:00
public Point Location
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
return new Point ( _startupParameters . Left , _startupParameters . Top ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var left = 0 ;
var top = 0 ;
Invoke ( ( ) = > Photino_GetPosition ( _nativeInstance , out left , out top ) ) ;
return new Point ( left , top ) ;
}
set
{
if ( Location . X ! = value . X | | Location . Y ! = value . Y )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
_startupParameters . Left = value . X ;
_startupParameters . Top = value . Y ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
else
Invoke ( ( ) = > Photino_SetPosition ( _nativeInstance , value . X , value . Y ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the native window Left (X) coordinate in pixels.
/// This represents the horizontal position of the window relative to the screen.
/// Default value is 0 which means the window will be aligned to the left edge of the screen.
/// </summary>
/// <seealso cref="UseOsDefaultLocation" />
2022-09-14 12:39:23 -05:00
public int Left
{
get = > Location . X ;
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( Location . X ! = value )
Location = new Point ( value , Location . Y ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets whether the native window is maximized.
/// Default is false.
/// </summary>
2022-09-14 12:39:23 -05:00
public bool Maximized
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . Maximized ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
bool maximized = false ;
Invoke ( ( ) = > Photino_GetMaximized ( _nativeInstance , out maximized ) ) ;
return maximized ;
}
set
{
if ( Maximized ! = value )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . Maximized = value ;
else
Invoke ( ( ) = > Photino_SetMaximized ( _nativeInstance , value ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-08-24 12:19:10 -06:00
///<summary>Gets or set the maximum size of the native window in pixels.</summary>
public Point MaxSize
{
get = > new Point ( MaxWidth , MaxHeight ) ;
set
{
if ( MaxWidth ! = value . X | | MaxHeight ! = value . Y )
{
if ( _nativeInstance = = IntPtr . Zero )
{
_startupParameters . MaxWidth = value . X ;
_startupParameters . MaxHeight = value . Y ;
}
else
Invoke ( ( ) = > Photino_SetMaxSize ( _nativeInstance , value . X , value . Y ) ) ;
}
}
}
///<summary>Gets or sets the native window maximum height in pixels.</summary>
private int _maxHeight = int . MaxValue ;
public int MaxHeight
{
get = > _maxHeight ;
set
{
if ( _maxHeight ! = value )
{
MaxSize = new Point ( MaxSize . X , value ) ;
2024-10-24 09:34:53 -06:00
_maxHeight = value ;
2023-08-24 12:19:10 -06:00
}
}
}
///<summary>Gets or sets the native window maximum height in pixels.</summary>
private int _maxWidth = int . MaxValue ;
public int MaxWidth
{
get = > _maxWidth ;
set
{
if ( _maxWidth ! = value )
{
MaxSize = new Point ( value , MaxSize . Y ) ;
2024-10-24 09:34:53 -06:00
_maxWidth = value ;
2023-08-24 12:19:10 -06:00
}
}
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets whether the native window is minimized (hidden).
/// Default is false.
/// </summary>
2022-09-14 12:39:23 -05:00
public bool Minimized
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . Minimized ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
bool minimized = false ;
Invoke ( ( ) = > Photino_GetMinimized ( _nativeInstance , out minimized ) ) ;
return minimized ;
}
set
{
if ( Minimized ! = value )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . Minimized = value ;
else
Invoke ( ( ) = > Photino_SetMinimized ( _nativeInstance , value ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-08-24 12:19:10 -06:00
///<summary>Gets or set the minimum size of the native window in pixels.</summary>
public Point MinSize
{
get = > new Point ( MinWidth , MinHeight ) ;
set
{
if ( MinWidth ! = value . X | | MinHeight ! = value . Y )
{
if ( _nativeInstance = = IntPtr . Zero )
{
_startupParameters . MinWidth = value . X ;
_startupParameters . MinHeight = value . Y ;
}
else
Invoke ( ( ) = > Photino_SetMinSize ( _nativeInstance , value . X , value . Y ) ) ;
}
}
}
///<summary>Gets or sets the native window minimum height in pixels.</summary>
private int _minHeight = 0 ;
public int MinHeight
{
get = > _minHeight ;
set
{
if ( _minHeight ! = value )
{
MinSize = new Point ( MinSize . X , value ) ;
2024-10-24 09:34:53 -06:00
_minHeight = value ;
2023-08-24 12:19:10 -06:00
}
}
}
///<summary>Gets or sets the native window minimum height in pixels.</summary>
private int _minWidth = 0 ;
public int MinWidth
{
get = > _minWidth ;
set
{
if ( _minWidth ! = value )
{
MinSize = new Point ( value , MinSize . Y ) ;
2024-10-24 09:34:53 -06:00
_minWidth = value ;
2023-08-24 12:19:10 -06:00
}
}
}
2025-10-22 18:33:07 -05:00
private PhotinoWindow _dotNetParent ;
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets the reference to parent PhotinoWindow instance.
/// This property can only be set in the constructor and it is optional.
/// </summary>
2022-09-14 12:39:23 -05:00
public PhotinoWindow Parent { get { return _dotNetParent ; } }
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets whether the native window can be resized by the user.
/// Default is true.
/// </summary>
2022-09-14 12:39:23 -05:00
public bool Resizable
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . Resizable ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var resizable = false ;
Invoke ( ( ) = > Photino_GetResizable ( _nativeInstance , out resizable ) ) ;
return resizable ;
}
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( Resizable ! = value )
2021-06-25 13:54:01 -06:00
{
if ( _nativeInstance = = IntPtr . Zero )
2022-09-14 12:39:23 -05:00
_startupParameters . Resizable = value ;
else
Invoke ( ( ) = > Photino_SetResizable ( _nativeInstance , value ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the native window Size. This represents the width and the height of the window in pixels.
/// The default Size is 0,0.
/// </summary>
/// <seealso cref="UseOsDefaultSize"/>
2022-09-14 12:39:23 -05:00
public Size Size
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
return new Size ( _startupParameters . Width , _startupParameters . Height ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var width = 0 ;
var height = 0 ;
Invoke ( ( ) = > Photino_GetSize ( _nativeInstance , out width , out height ) ) ;
return new Size ( width , height ) ;
}
set
{
if ( Size . Width ! = value . Width | | Size . Height ! = value . Height )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
_startupParameters . Height = value . Height ;
_startupParameters . Width = value . Width ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
else
Invoke ( ( ) = > Photino_SetSize ( _nativeInstance , value . Width , value . Height ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-10-19 13:20:07 -06:00
/// <summary>
/// Gets or sets platform specific initialization parameters for the native browser control on startup.
/// Default is none.
///WINDOWS: WebView2 specific string. Space separated.
///https://peter.sh/experiments/chromium-command-line-switches/
///https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2environmentoptions.additionalbrowserarguments?view=webview2-dotnet-1.0.1938.49&viewFallbackFrom=webview2-dotnet-1.0.1901.177view%3Dwebview2-1.0.1901.177
///https://www.chromium.org/developers/how-tos/run-chromium-with-flags/
///LINUX: Webkit2Gtk specific string. Enter parameter names and values as JSON string.
///e.g. { "set_enable_encrypted_media": true }
///https://webkitgtk.org/reference/webkit2gtk/2.5.1/WebKitSettings.html
///https://lazka.github.io/pgi-docs/WebKit2-4.0/classes/Settings.html
///MAC: Webkit specific string. Enter parameter names and values as JSON string.
///e.g. { "minimumFontSize": 8 }
///https://developer.apple.com/documentation/webkit/wkwebviewconfiguration?language=objc
///https://developer.apple.com/documentation/webkit/wkpreferences?language=objc
/// </summary>
public string BrowserControlInitParameters
{
get
{
2024-08-30 11:38:25 -06:00
return _startupParameters . BrowserControlInitParameters ;
2023-10-19 13:20:07 -06:00
}
set
{
2024-08-30 11:38:25 -06:00
var ss = _startupParameters . BrowserControlInitParameters ;
2023-10-19 13:20:07 -06:00
if ( string . Compare ( ss , value , true ) ! = 0 )
{
if ( _nativeInstance = = IntPtr . Zero )
2024-08-30 11:38:25 -06:00
_startupParameters . BrowserControlInitParameters = value ;
2023-10-19 13:20:07 -06:00
else
throw new ApplicationException ( $"{nameof(ss)} cannot be changed after Photino Window is initialized" ) ;
}
}
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets an HTML string that the browser control will render when initialized.
/// Default is none.
/// </summary>
/// <remarks>
/// Either StartString or StartUrl must be specified.
/// </remarks>
/// <seealso cref="StartUrl" />
/// <exception cref="ApplicationException">
/// Thrown if trying to set value after native window is initalized.
/// </exception>
2022-09-14 12:39:23 -05:00
public string StartString
{
get
{
2024-08-30 11:38:25 -06:00
return _startupParameters . StartString ;
2022-09-14 12:39:23 -05:00
}
set
2021-06-25 13:54:01 -06:00
{
2024-08-30 11:38:25 -06:00
var ss = _startupParameters . StartString ;
2022-09-14 12:39:23 -05:00
if ( string . Compare ( ss , value , true ) ! = 0 )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance ! = IntPtr . Zero )
throw new ApplicationException ( $"{nameof(ss)} cannot be changed after Photino Window is initialized" ) ;
LoadRawString ( value ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets an URL that the browser control will navigate to when initialized.
/// Default is none.
/// </summary>
/// <remarks>
/// Either StartString or StartUrl must be specified.
/// </remarks>
/// <seealso cref="StartString" />
/// <exception cref="ApplicationException">
/// Thrown if trying to set value after native window is initalized.
/// </exception>
2022-09-14 12:39:23 -05:00
public string StartUrl
{
get
{
2024-08-30 11:38:25 -06:00
return _startupParameters . StartUrl ;
2022-09-14 12:39:23 -05:00
}
set
{
2024-08-30 11:38:25 -06:00
var su = _startupParameters . StartUrl ;
2022-09-14 12:39:23 -05:00
if ( string . Compare ( su , value , true ) ! = 0 )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance ! = IntPtr . Zero )
throw new ApplicationException ( $"{nameof(su)} cannot be changed after Photino Window is initialized" ) ;
Load ( value ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the local path to store temp files for browser control.
/// Default is the user's AppDataLocal folder.
/// </summary>
/// <remarks>
/// Only available on Windows.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown if platform is not Windows.
/// </exception>
2022-09-14 12:39:23 -05:00
public string TemporaryFilesPath
{
get
{
2024-08-30 11:38:25 -06:00
return _startupParameters . TemporaryFilesPath ;
2022-09-14 12:39:23 -05:00
}
set
2021-06-25 13:54:01 -06:00
{
2024-08-30 11:38:25 -06:00
var tfp = _startupParameters . TemporaryFilesPath ;
2022-09-14 12:39:23 -05:00
if ( tfp ! = value )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance ! = IntPtr . Zero )
throw new ApplicationException ( $"{nameof(tfp)} cannot be changed after Photino Window is initialized" ) ;
2024-08-30 11:38:25 -06:00
_startupParameters . TemporaryFilesPath = value ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2024-10-17 13:46:43 -06:00
/// <summary>
/// Gets or sets the registration Id for doing toast notifications.
/// Default is to use the window title.
/// </summary>
/// <remarks>
/// Only available on Windows.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown if platform is not Windows.
/// </exception>
public string NotificationRegistrationId
{
get
{
return _startupParameters . NotificationRegistrationId ;
}
set
{
var nri = _startupParameters . NotificationRegistrationId ;
if ( nri ! = value )
{
if ( _nativeInstance ! = IntPtr . Zero )
throw new ApplicationException ( $"{nameof(nri)} cannot be changed after Photino Window is initialized" ) ;
_startupParameters . NotificationRegistrationId = value ;
}
}
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the native window title.
/// Default is "Photino".
/// </summary>
2022-09-14 12:39:23 -05:00
public string Title
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
2024-08-30 11:38:25 -06:00
return _startupParameters . Title ;
2022-09-14 12:39:23 -05:00
var title = string . Empty ;
Invoke ( ( ) = >
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
var ptr = Photino_GetTitle ( _nativeInstance ) ;
title = Marshal . PtrToStringAuto ( ptr ) ;
} ) ;
return title ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( Title ! = value )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
// Due to Linux/Gtk platform limitations, the window title has to be no more than 31 chars
if ( value . Length > 31 & & IsLinuxPlatform )
value = value [ . . 31 ] ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
2024-08-30 11:38:25 -06:00
_startupParameters . Title = value ;
2022-09-14 12:39:23 -05:00
else
Invoke ( ( ) = > Photino_SetTitle ( _nativeInstance , value ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the native window Top (Y) coordinate in pixels.
/// Default is 0.
/// </summary>
/// <seealso cref="UseOsDefaultLocation"/>
2022-09-14 12:39:23 -05:00
public int Top
{
get = > Location . Y ;
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( Location . Y ! = value )
Location = new Point ( Location . X , value ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets whether the native window is always at the top of the z-order.
/// Default is false.
/// </summary>
2022-09-14 12:39:23 -05:00
public bool Topmost
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . Topmost ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var topmost = false ;
Invoke ( ( ) = > Photino_GetTopmost ( _nativeInstance , out topmost ) ) ;
return topmost ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( Topmost ! = value )
2021-06-25 13:54:01 -06:00
{
if ( _nativeInstance = = IntPtr . Zero )
2022-09-14 12:39:23 -05:00
_startupParameters . Topmost = value ;
2021-06-25 13:54:01 -06:00
else
2024-06-14 14:14:01 -06:00
Invoke ( ( ) = > Photino_SetTopmost ( _nativeInstance , value ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true the native window starts up at the OS Default location.
/// Default is true.
/// </summary>
/// <remarks>
/// Overrides Left (X) and Top (Y) properties.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown if trying to set value after native window is initalized.
/// </exception>
2022-09-14 12:39:23 -05:00
public bool UseOsDefaultLocation
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
return _startupParameters . UseOsDefaultLocation ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( UseOsDefaultLocation ! = value )
_startupParameters . UseOsDefaultLocation = value ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
else
throw new ApplicationException ( "UseOsDefaultLocation can only be set before the native window is instantiated." ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true the native window starts at the OS Default size.
/// Default is true.
/// </summary>
/// <remarks>
/// Overrides Height and Width properties.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown if trying to set value after native window is initalized.
/// </exception>
2022-09-14 12:39:23 -05:00
public bool UseOsDefaultSize
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
return _startupParameters . UseOsDefaultSize ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( UseOsDefaultSize ! = value )
_startupParameters . UseOsDefaultSize = value ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
else
throw new ApplicationException ( "UseOsDefaultSize can only be set before the native window is instantiated." ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WebMessageReceived event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WebMessageReceived"/>
2022-09-14 12:39:23 -05:00
public EventHandler < string > WebMessageReceivedHandler
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
return WebMessageReceived ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
WebMessageReceived + = value ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or Sets the native window width in pixels.
/// Default is 0.
/// </summary>
/// <seealso cref="UseOsDefaultSize"/>
2022-09-14 12:39:23 -05:00
public int Width
{
get = > Size . Width ;
set
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
var currentSize = Size ;
if ( currentSize . Width ! = value )
Size = new Size ( value , currentSize . Height ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the handlers for WindowClosing event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowClosing" />
2022-09-14 12:39:23 -05:00
public NetClosingDelegate WindowClosingHandler
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
return WindowClosing ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
set
2021-08-26 17:59:12 -04:00
{
2022-09-14 12:39:23 -05:00
WindowClosing + = value ;
2021-08-26 17:59:12 -04:00
}
2022-09-14 12:39:23 -05:00
}
2021-08-26 17:59:12 -04:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WindowCreating event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowCreating"/>
2022-09-14 12:39:23 -05:00
public EventHandler WindowCreatingHandler
{
get
2021-08-26 17:59:12 -04:00
{
2022-09-14 12:39:23 -05:00
return WindowCreating ;
2021-08-26 17:59:12 -04:00
}
2022-09-14 12:39:23 -05:00
set
{
WindowCreating + = value ;
2021-08-28 14:33:49 -04:00
}
2022-09-14 12:39:23 -05:00
}
2021-08-28 14:33:49 -04:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WindowCreated event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowCreated"/>
2022-09-14 12:39:23 -05:00
public EventHandler WindowCreatedHandler
{
get
{
return WindowCreated ;
2021-08-28 14:33:49 -04:00
}
2022-09-14 12:39:23 -05:00
set
{
WindowCreated + = value ;
2021-08-28 14:33:49 -04:00
}
2022-09-14 12:39:23 -05:00
}
2021-08-26 17:59:12 -04:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WindowLocationChanged event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowLocationChanged"/>
2022-09-14 12:39:23 -05:00
public EventHandler < Point > WindowLocationChangedHandler
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
return WindowLocationChanged ;
}
set
{
WindowLocationChanged + = value ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WindowSizeChanged event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowSizeChanged"/>
2022-09-14 12:39:23 -05:00
public EventHandler < Size > WindowSizeChangedHandler
{
get
{
return WindowSizeChanged ;
}
set
{
WindowSizeChanged + = value ;
}
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WindowFocusIn event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowFocusIn"/>
2022-09-14 12:39:23 -05:00
public EventHandler WindowFocusInHandler
{
get
{
return WindowFocusIn ;
}
set
{
WindowFocusIn + = value ;
}
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WindowFocusOut event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowFocusOut"/>
2022-09-14 12:39:23 -05:00
public EventHandler WindowFocusOutHandler
{
get
{
return WindowFocusOut ;
}
set
{
WindowFocusOut + = value ;
}
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WindowMaximized event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowMaximized"/>
2022-09-14 12:39:23 -05:00
public EventHandler WindowMaximizedHandler
{
get
{
return WindowMaximized ;
}
set
{
WindowMaximized + = value ;
}
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WindowRestored event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowRestored"/>
2022-09-14 12:39:23 -05:00
public EventHandler WindowRestoredHandler
{
get
{
return WindowRestored ;
}
set
{
WindowRestored + = value ;
}
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets handlers for WindowMinimized event.
/// Set assigns a new handler to the event.
/// </summary>
/// <seealso cref="WindowMinimized"/>
2022-09-14 12:39:23 -05:00
public EventHandler WindowMinimizedHandler
{
get
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
return WindowMinimized ;
}
set
{
WindowMinimized + = value ;
}
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the native browser control <see cref="PhotinoWindow.Zoom"/>.
/// Default is 100.
/// </summary>
/// <example>100 = 100%, 50 = 50%</example>
2022-09-14 12:39:23 -05:00
public int Zoom
{
get
{
if ( _nativeInstance = = IntPtr . Zero )
return _startupParameters . Zoom ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var zoom = 0 ;
Invoke ( ( ) = > Photino_GetZoom ( _nativeInstance , out zoom ) ) ;
return zoom ;
}
set
{
if ( Zoom ! = value )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
_startupParameters . Zoom = value ;
else
Invoke ( ( ) = > Photino_SetZoom ( _nativeInstance , value ) ) ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Gets or sets the logging verbosity to standard output (Console/Terminal).
/// 0 = Critical Only
/// 1 = Critical and Warning
/// 2 = Verbose
/// >2 = All Details
/// Default is 2.
/// </summary>
2022-09-14 12:39:23 -05:00
public int LogVerbosity { get ; set ; } = 2 ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
//CONSTRUCTOR
2023-07-07 22:44:17 +02:00
/// <summary>
/// Initializes a new instance of the PhotinoWindow class.
/// </summary>
/// <remarks>
/// This class represents a native window with a native browser control taking up the entire client area.
/// If a parent window is specified, this window will be created as a child of the specified parent window.
/// </remarks>
/// <param name="parent">The parent PhotinoWindow. This is optional and defaults to null.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow ( PhotinoWindow parent = null )
{
_dotNetParent = parent ;
_managedThreadId = Environment . CurrentManagedThreadId ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
//This only has to be done once
if ( _nativeType = = IntPtr . Zero )
2023-03-08 15:26:39 -07:00
_nativeType = NativeLibrary . GetMainProgramHandle ( ) ;
2022-09-14 12:39:23 -05:00
//Wire up handlers from C++ to C#
_startupParameters . ClosingHandler = OnWindowClosing ;
_startupParameters . ResizedHandler = OnSizeChanged ;
_startupParameters . MaximizedHandler = OnMaximized ;
_startupParameters . RestoredHandler = OnRestored ;
_startupParameters . MinimizedHandler = OnMinimized ;
_startupParameters . MovedHandler = OnLocationChanged ;
_startupParameters . FocusInHandler = OnFocusIn ;
_startupParameters . FocusOutHandler = OnFocusOut ;
_startupParameters . WebMessageReceivedHandler = OnWebMessageReceived ;
_startupParameters . CustomSchemeHandler = OnCustomScheme ;
}
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
//FLUENT METHODS FOR INITIALIZING STARTUP PARAMETERS FOR NEW WINDOWS
//CAN ALSO BE CALLED AFTER INITIALIZATION TO SET VALUES
//ONE OF THESE 3 METHODS *MUST* BE CALLED PRIOR TO CALLING WAITFORCLOSE() OR CREATECHILDWINDOW()
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Dispatches an Action to the UI thread if called from another thread.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="workItem">The delegate encapsulating a method / action to be executed in the UI thread.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow Invoke ( Action workItem )
{
// If we're already on the UI thread, no need to dispatch
if ( Environment . CurrentManagedThreadId = = _managedThreadId )
workItem ( ) ;
else
Photino_Invoke ( _nativeInstance , workItem . Invoke ) ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Loads a specified <see cref="Uri"/> into the browser control.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <remarks>
/// Load() or LoadString() must be called before native window is initialized.
/// </remarks>
/// <param name="uri">A Uri pointing to the file or the URL to load.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow Load ( Uri uri )
{
Log ( $".Load({uri})" ) ;
if ( _nativeInstance = = IntPtr . Zero )
2024-08-30 11:38:25 -06:00
_startupParameters . StartUrl = uri . ToString ( ) ;
2022-09-14 12:39:23 -05:00
else
Invoke ( ( ) = > Photino_NavigateToUrl ( _nativeInstance , uri . ToString ( ) ) ) ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Loads a specified path into the browser control.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <remarks>
/// Load() or LoadString() must be called before native window is initialized.
/// </remarks>
/// <param name="path">A path pointing to the ressource to load.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow Load ( string path )
{
Log ( $".Load({path})" ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
// – – – – – – – – – – – – – – – – – – – – – –
// SECURITY RISK!
// This needs validation!
// – – – – – – – – – – – – – – – – – – – – – –
// Open a web URL string path
if ( path . Contains ( "http://" ) | | path . Contains ( "https://" ) )
return Load ( new Uri ( path ) ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
// Open a file resource string path
string absolutePath = Path . GetFullPath ( path ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
// For bundled app it can be necessary to consider
// the app context base directory. Check there too.
if ( File . Exists ( absolutePath ) = = false )
{
absolutePath = $"{System.AppContext.BaseDirectory}/{path}" ;
2021-06-25 13:54:01 -06:00
if ( File . Exists ( absolutePath ) = = false )
{
2022-09-14 12:39:23 -05:00
Log ( $" ** File \" { path } \ " could not be found." ) ;
return this ;
2021-06-25 13:54:01 -06:00
}
}
2022-09-14 12:39:23 -05:00
return Load ( new Uri ( absolutePath , UriKind . Absolute ) ) ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Loads a raw string into the browser control.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <remarks>
/// Used to load HTML into the browser control directly.
/// Load() or LoadString() must be called before native window is initialized.
/// </remarks>
/// <param name="content">Raw content (such as HTML)</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow LoadRawString ( string content )
{
var shortContent = content . Length > 50 ? string . Concat ( content . AsSpan ( 0 , 50 ) , "..." ) : content ;
Log ( $".LoadRawString({shortContent})" ) ;
if ( _nativeInstance = = IntPtr . Zero )
2024-08-30 11:38:25 -06:00
_startupParameters . StartString = content ;
2022-09-14 12:39:23 -05:00
else
Invoke ( ( ) = > Photino_NavigateToString ( _nativeInstance , content ) ) ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Centers the native window on the primary display.
/// </summary>
/// <remarks>
/// If called prior to window initialization, overrides Left (X) and Top (Y) properties.
/// </remarks>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <seealso cref="UseOsDefaultLocation" />
2022-09-14 12:39:23 -05:00
public PhotinoWindow Center ( )
{
Log ( ".Center()" ) ;
Centered = true ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Moves the native window to the specified location on the screen in pixels using a Point.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="location">Position as <see cref="Point"/></param>
/// <param name="allowOutsideWorkArea">Whether the window can go off-screen (work area)</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow MoveTo ( Point location , bool allowOutsideWorkArea = false )
{
Log ( $".MoveTo({location}, {allowOutsideWorkArea})" ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
if ( LogVerbosity > 2 )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
Log ( $" Current location: {Location}" ) ;
Log ( $" New location: {location}" ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
// If the window is outside of the work area,
// recalculate the position and continue.
//When window isn't initialized yet, cannot determine screen size.
if ( allowOutsideWorkArea = = false & & _nativeInstance ! = IntPtr . Zero )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
int horizontalWindowEdge = location . X + Width ;
int verticalWindowEdge = location . Y + Height ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
int horizontalWorkAreaEdge = MainMonitor . WorkArea . Width ;
int verticalWorkAreaEdge = MainMonitor . WorkArea . Height ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
bool isOutsideHorizontalWorkArea = horizontalWindowEdge > horizontalWorkAreaEdge ;
bool isOutsideVerticalWorkArea = verticalWindowEdge > verticalWorkAreaEdge ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var locationInsideWorkArea = new Point (
isOutsideHorizontalWorkArea ? horizontalWorkAreaEdge - Width : location . X ,
isOutsideVerticalWorkArea ? verticalWorkAreaEdge - Height : location . Y
) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
location = locationInsideWorkArea ;
}
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
// Bug:
// For some reason the vertical position is not handled correctly.
// Whenever a positive value is set, the window appears at the
// very bottom of the screen and the only visible thing is the
// application window title bar. As a workaround we make a
// negative value out of the vertical position to "pull" the window up.
// Note:
// This behavior seems to be a macOS thing. In the Photino.Native
// project files it is commented to be expected behavior for macOS.
// There is some code trying to mitigate this problem but it might
// not work as expected. Further investigation is necessary.
2023-10-26 10:27:18 -05:00
// Update:
// This behavior seems to have changed with macOS Sonoma.
// Therefore we determine the version of macOS and only apply the
// workaround for older versions.
if ( IsMacOsPlatform & & MacOsVersion . Major < 23 )
2022-09-14 12:39:23 -05:00
{
var workArea = MainMonitor . WorkArea . Size ;
location . Y = location . Y > = 0
? location . Y - workArea . Height
: location . Y ;
}
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
Location = location ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Moves the native window to the specified location on the screen in pixels
/// using <see cref="PhotinoWindow.Left"/> (X) and <see cref="PhotinoWindow.Top"/> (Y) properties.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="left">Position from left in pixels</param>
/// <param name="top">Position from top in pixels</param>
/// <param name="allowOutsideWorkArea">Whether the window can go off-screen (work area)</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow MoveTo ( int left , int top , bool allowOutsideWorkArea = false )
{
Log ( $".MoveTo({left}, {top}, {allowOutsideWorkArea})" ) ;
return MoveTo ( new Point ( left , top ) , allowOutsideWorkArea ) ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Moves the native window relative to its current location on the screen
/// using a <see cref="Point"/>.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="offset">Relative offset</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow Offset ( Point offset )
{
Log ( $".Offset({offset})" ) ;
var location = Location ;
int left = location . X + offset . X ;
int top = location . Y + offset . Y ;
return MoveTo ( left , top ) ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Moves the native window relative to its current location on the screen in pixels
/// using <see cref="PhotinoWindow.Left"/> (X) and <see cref="PhotinoWindow.Top"/> (Y) properties.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="left">Relative offset from left in pixels</param>
/// <param name="top">Relative offset from top in pixels</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow Offset ( int left , int top )
{
Log ( $".Offset({left}, {top})" ) ;
return Offset ( new Point ( left , top ) ) ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true, the native window will appear without a title bar or border.
/// By default, this is set to false.
/// </summary>
/// <remarks>
/// The user has to supply titlebar, border, dragging and resizing manually.
/// </remarks>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="chromeless">Whether the window should be chromeless</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetChromeless ( bool chromeless )
{
Log ( $".SetChromeless({chromeless})" ) ;
if ( _nativeInstance ! = IntPtr . Zero )
2024-10-10 13:03:37 -06:00
throw new ApplicationException ( "Chromeless can only be set before the native window is instantiated." ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
_startupParameters . Chromeless = chromeless ;
return this ;
}
2021-06-25 13:54:01 -06:00
2024-05-08 21:10:53 +03:00
/// <summary>
2025-10-22 18:33:07 -05:00
/// Set the parent window
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="parent">The window that should be used as this window's parent</param>
public PhotinoWindow SetParent ( PhotinoWindow parent )
{
Log ( $".SetParent({parent.Id})" ) ;
if ( _nativeInstance ! = IntPtr . Zero )
throw new ApplicationException ( "Parent window can only be set before the native window is instantiated." ) ;
_dotNetParent = parent ;
return this ;
}
2024-05-08 21:10:53 +03:00
/// <summary>
/// When true, the native window can be displayed with transparent background.
/// Chromeless must be set to true. Html document's body background must have alpha-based value.
/// By default, this is set to false.
/// </summary>
public PhotinoWindow SetTransparent ( bool enabled )
{
Log ( $".SetTransparent({enabled})" ) ;
Transparent = enabled ;
return this ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true, the user can access the browser control's context menu.
/// By default, this is set to true.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="enabled">Whether the context menu should be available</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetContextMenuEnabled ( bool enabled )
{
Log ( $".SetContextMenuEnabled({enabled})" ) ;
ContextMenuEnabled = enabled ;
return this ;
}
2021-06-25 13:54:01 -06:00
2025-03-11 11:55:06 +01:00
/// <summary>
/// When true, the user can zoom.
/// By default, this is set to true.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="enabled">Whether the zoom should be available</param>
public PhotinoWindow SetZoomEnabled ( bool enabled )
{
Log ( $".SetZoomEnabled({enabled})" ) ;
ZoomEnabled = enabled ;
return this ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true, the user can access the browser control's developer tools.
/// By default, this is set to true.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="enabled">Whether developer tools should be available</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetDevToolsEnabled ( bool enabled )
{
Log ( $".SetDevTools({enabled})" ) ;
DevToolsEnabled = enabled ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// When set to true, the native window will cover the entire screen, similar to kiosk mode.
/// By default, this is set to false.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="fullScreen">Whether the window should be fullscreen</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetFullScreen ( bool fullScreen )
{
Log ( $".SetFullScreen({fullScreen})" ) ;
FullScreen = fullScreen ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
///<summary>
/// When set to true, the native browser control grants all requests for access to local resources
/// such as the users camera and microphone. By default, this is set to true.
/// </summary>
/// <remarks>
/// This only works on Windows.
/// </remarks>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="grant">Whether permissions should be automatically granted.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetGrantBrowserPermissions ( bool grant )
{
Log ( $".SetGrantBrowserPermission({grant})" ) ;
GrantBrowserPermissions = grant ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-10-19 13:20:07 -06:00
/// <summary>
/// Sets <see cref="PhotinoWindow.UserAgent"/>. Sets the user agent on the browser control at initialization.
/// </summary>
/// <param name="userAgent"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
2023-09-14 12:24:07 -05:00
public PhotinoWindow SetUserAgent ( string userAgent )
{
Log ( $".SetUserAgent({userAgent})" ) ;
UserAgent = userAgent ;
return this ;
}
2023-10-19 13:20:07 -06:00
/// <summary>
/// Sets <see cref="PhotinoWindow.BrowserControlInitParameters"/> platform specific initialization parameters for the native browser control on startup.
/// Default is none.
/// <remarks>
/// WINDOWS: WebView2 specific string. Space separated.
/// https://peter.sh/experiments/chromium-command-line-switches/
/// https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2environmentoptions.additionalbrowserarguments?view=webview2-dotnet-1.0.1938.49&viewFallbackFrom=webview2-dotnet-1.0.1901.177view%3Dwebview2-1.0.1901.177
/// https://www.chromium.org/developers/how-tos/run-chromium-with-flags/
/// LINUX: Webkit2Gtk specific string. Enter parameter names and values as JSON string.
/// e.g. { "set_enable_encrypted_media": true }
/// https://webkitgtk.org/reference/webkit2gtk/2.5.1/WebKitSettings.html
/// https://lazka.github.io/pgi-docs/WebKit2-4.0/classes/Settings.html
/// MAC: Webkit specific string. Enter parameter names and values as JSON string.
/// e.g. { "minimumFontSize": 8 }
/// https://developer.apple.com/documentation/webkit/wkwebviewconfiguration?language=objc
/// https://developer.apple.com/documentation/webkit/wkpreferences?language=objc
/// </remarks>
/// <param name="parameters"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
/// </summary>
public PhotinoWindow SetBrowserControlInitParameters ( string parameters )
{
Log ( $".SetBrowserControlInitParameters({parameters})" ) ;
BrowserControlInitParameters = parameters ;
return this ;
}
2024-10-17 13:46:43 -06:00
/// <summary>
/// Sets the registration id for toast notifications.
/// </summary>
/// <remarks>
/// Only available on Windows.
/// Defaults to window title if not specified.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown if platform is not Windows.
/// </exception>
/// <param name="notificationRegistrationId"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
public PhotinoWindow SetNotificationRegistrationId ( string notificationRegistrationId )
{
Log ( $".SetNotificationRegistrationId({notificationRegistrationId})" ) ;
NotificationRegistrationId = notificationRegistrationId ;
return this ;
}
2023-10-19 13:20:07 -06:00
/// <summary>
/// Sets <see cref="PhotinoWindow.MediaAutoplayEnabled"/> on the browser control at initialization.
/// </summary>
/// <param name="enable"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
2023-09-14 12:24:07 -05:00
public PhotinoWindow SetMediaAutoplayEnabled ( bool enable )
{
Log ( $".SetMediaAutoplayEnabled({enable})" ) ;
MediaAutoplayEnabled = enable ;
return this ;
}
2023-10-19 13:20:07 -06:00
/// <summary>
/// Sets <see cref="PhotinoWindow.FileSystemAccessEnabled"/> on the browser control at initialization.
/// </summary>
/// <param name="enable"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
2023-09-14 12:24:07 -05:00
public PhotinoWindow SetFileSystemAccessEnabled ( bool enable )
{
Log ( $".SetFileSystemAccessEnabled({enable})" ) ;
FileSystemAccessEnabled = enable ;
return this ;
}
2023-10-19 13:20:07 -06:00
/// <summary>
/// Sets <see cref="PhotinoWindow.WebSecurityEnabled"/> on the browser control at initialization.
/// </summary>
/// <param name="enable"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
2023-09-14 12:24:07 -05:00
public PhotinoWindow SetWebSecurityEnabled ( bool enable )
{
Log ( $".SetWebSecurityEnabled({enable})" ) ;
WebSecurityEnabled = enable ;
return this ;
}
2023-10-19 13:20:07 -06:00
/// <summary>
/// Sets <see cref="PhotinoWindow.JavascriptClipboardAccessEnabled"/> on the browser control at initialization.
/// </summary>
/// <param name="enable"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
2023-09-14 12:24:07 -05:00
public PhotinoWindow SetJavascriptClipboardAccessEnabled ( bool enable )
{
Log ( $".SetJavascriptClipboardAccessEnabled({enable})" ) ;
JavascriptClipboardAccessEnabled = enable ;
return this ;
}
2023-10-19 13:20:07 -06:00
/// <summary>
/// Sets <see cref="PhotinoWindow.MediaStreamEnabled"/> on the browser control at initialization.
/// </summary>
/// <param name="enable"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
2023-09-14 12:24:07 -05:00
public PhotinoWindow SetMediaStreamEnabled ( bool enable )
{
Log ( $".SetMediaStreamEnabled({enable})" ) ;
MediaStreamEnabled = enable ;
return this ;
}
2023-10-19 13:20:07 -06:00
/// <summary>
/// Sets <see cref="PhotinoWindow.SmoothScrollingEnabled"/> on the browser control at initialization.
/// </summary>
/// <param name="enable"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
2023-09-14 12:24:07 -05:00
public PhotinoWindow SetSmoothScrollingEnabled ( bool enable )
{
Log ( $".SetSmoothScrollingEnabled({enable})" ) ;
SmoothScrollingEnabled = enable ;
return this ;
}
2024-01-04 10:58:18 -07:00
/// <summary>
/// Sets <see cref="PhotinoWindow.IgnoreCertificateErrorsEnabled"/> on the browser control at initialization.
/// </summary>
/// <param name="enable"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
public PhotinoWindow SetIgnoreCertificateErrorsEnabled ( bool enable )
{
Log ( $".SetIgnoreCertificateErrorsEnabled({enable})" ) ;
IgnoreCertificateErrorsEnabled = enable ;
return this ;
}
2023-09-14 12:24:07 -05:00
2024-10-17 13:46:43 -06:00
/// <summary>
/// Sets whether ShowNotification() can be called.
/// </summary>
/// <remarks>
/// Only available on Windows.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown if platform is not Windows.
/// </exception>
/// <param name="enable"></param>
/// <returns>Returns the current <see cref="PhotinoWindow"/> instance.</returns>
public PhotinoWindow SetNotificationsEnabled ( bool enable )
{
Log ( $".SetNotificationsEnabled({enable})" ) ;
NotificationsEnabled = enable ;
return this ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the native window <see cref="PhotinoWindow.Height"/> in pixels.
/// Default is 0.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <seealso cref="UseOsDefaultSize"/>
/// <param name="height">Height in pixels</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetHeight ( int height )
{
Log ( $".SetHeight({height})" ) ;
Height = height ;
return this ;
}
2025-03-14 23:17:11 -04:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the icon file for the native window title bar.
/// The file must be located on the local machine and cannot be a URL. The default is none.
/// </summary>
/// <remarks>
/// This only works on Windows and Linux.
/// </remarks>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <exception cref="System.ArgumentException">Icon file: {value} does not exist.</exception>
/// <param name="iconFile">The file path to the icon.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetIconFile ( string iconFile )
{
Log ( $".SetIconFile({iconFile})" ) ;
IconFile = iconFile ;
return this ;
}
2021-06-25 13:54:01 -06:00
2025-03-14 23:17:11 -04:00
/// <summary>
/// Sets the icon file for the native window title bar from an embedded resource.
/// The resource file is extracted to a temporary file, and its path is then set as the icon.
/// </summary>
/// <remarks>
/// This only works on Windows and Linux.
/// The resource file is expected to be embedded in the assembly from the `wwwroot` folder, and the provided namespace is used to locate the resource.
/// </remarks>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="resourceFileName">The name of the embedded resource file (e.g., "favicon.ico").</param>
/// <param name="resourceNamespace">
/// The namespace in which the embedded resource is located (e.g., "MyApp" or "MyCompany.MyApp").
/// This allows for specifying the custom namespace where the resource is embedded.
/// </param>
public PhotinoWindow SetIconFile ( string resourceFileName , string resourceNamespace )
{
string iconPath = ExtractEmbeddedResourceToTempFile ( resourceFileName , resourceNamespace ) ;
return iconPath ! = null ? SetIconFile ( iconPath ) : this ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the native window to a new <see cref="PhotinoWindow.Left"/> (X) coordinate in pixels.
/// Default is 0.
/// </summary>
/// <seealso cref="UseOsDefaultLocation" />
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="left">Position in pixels from the left (X).</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetLeft ( int left )
{
Log ( $".SetLeft({Left})" ) ;
Left = left ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets whether the native window can be resized by the user.
/// Default is true.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="resizable">Whether the window is resizable</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetResizable ( bool resizable )
{
Log ( $".SetResizable({resizable})" ) ;
Resizable = resizable ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the native window Size. This represents the <see cref="PhotinoWindow.Width"/> and the <see cref="PhotinoWindow.Height"/> of the window in pixels.
/// The default Size is 0,0.
/// </summary>
/// <seealso cref="UseOsDefaultSize"/>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="size">Width & Height</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetSize ( Size size )
{
Log ( $".SetSize({size})" ) ;
Size = size ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the native window Size. This represents the <see cref="PhotinoWindow.Width"/> and the <see cref="PhotinoWindow.Height"/> of the window in pixels.
/// The default Size is 0,0.
/// </summary>
/// <seealso cref="UseOsDefaultSize"/>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="width">Width in pixels</param>
/// <param name="height">Height in pixels</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetSize ( int width , int height )
{
Log ( $".SetSize({width}, {height})" ) ;
Size = new Size ( width , height ) ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the native window <see cref="PhotinoWindow.Left"/> (X) and <see cref="PhotinoWindow.Top"/> coordinates (Y) in pixels.
/// Default is 0,0 which means the window will be aligned to the top left edge of the screen.
/// </summary>
/// <seealso cref="UseOsDefaultLocation" />
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="location">Location as a <see cref="Point"/></param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetLocation ( Point location )
{
Log ( $".SetLocation({location})" ) ;
Location = location ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the logging verbosity to standard output (Console/Terminal).
/// 0 = Critical Only
/// 1 = Critical and Warning
/// 2 = Verbose
/// >2 = All Details
/// Default is 2.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="verbosity">Verbosity as integer</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetLogVerbosity ( int verbosity )
{
Log ( $".SetLogVerbosity({verbosity})" ) ;
LogVerbosity = verbosity ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets whether the native window is maximized.
/// Default is false.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="maximized">Whether the window should be maximized.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetMaximized ( bool maximized )
{
Log ( $".SetMaximized({maximized})" ) ;
Maximized = maximized ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-08-24 12:19:10 -06:00
///<summary>Native window maximum Width and Height in pixels.</summary>
public PhotinoWindow SetMaxSize ( int maxWidth , int maxHeight )
{
Log ( $".SetMaxSize({maxWidth}, {maxHeight})" ) ;
MaxSize = new Point ( maxWidth , maxHeight ) ;
return this ;
}
///<summary>Native window maximum Height in pixels.</summary>
public PhotinoWindow SetMaxHeight ( int maxHeight )
{
Log ( $".SetMaxHeight({maxHeight})" ) ;
MaxHeight = maxHeight ;
return this ;
}
///<summary>Native window maximum Width in pixels.</summary>
public PhotinoWindow SetMaxWidth ( int maxWidth )
{
Log ( $".SetMaxWidth({maxWidth})" ) ;
MaxWidth = maxWidth ;
return this ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets whether the native window is minimized (hidden).
/// Default is false.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="minimized">Whether the window should be minimized.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetMinimized ( bool minimized )
{
Log ( $".SetMinimized({minimized})" ) ;
Minimized = minimized ;
return this ;
}
2021-08-16 09:12:47 -06:00
2023-08-24 12:19:10 -06:00
///<summary>Native window maximum Width and Height in pixels.</summary>
public PhotinoWindow SetMinSize ( int minWidth , int minHeight )
{
Log ( $".SetMinSize({minWidth}, {minHeight})" ) ;
MinSize = new Point ( minWidth , minHeight ) ;
return this ;
}
///<summary>Native window maximum Height in pixels.</summary>
public PhotinoWindow SetMinHeight ( int minHeight )
{
Log ( $".SetMinHeight({minHeight})" ) ;
MinHeight = minHeight ;
return this ;
}
///<summary>Native window maximum Width in pixels.</summary>
public PhotinoWindow SetMinWidth ( int minWidth )
{
Log ( $".SetMinWidth({minWidth})" ) ;
MinWidth = minWidth ;
return this ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the local path to store temp files for browser control.
/// Default is the user's AppDataLocal folder.
/// </summary>
/// <remarks>
/// Only available on Windows.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown if platform is not Windows.
/// </exception>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="tempFilesPath">Path to temp files directory.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetTemporaryFilesPath ( string tempFilesPath )
{
Log ( $".SetTemporaryFilesPath({tempFilesPath})" ) ;
TemporaryFilesPath = tempFilesPath ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
2023-10-19 13:20:07 -06:00
/// Sets the native window <see cref="PhotinoWindow.Title"/>.
2023-07-07 22:44:17 +02:00
/// Default is "Photino".
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="title">Window title</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetTitle ( string title )
{
Log ( $".SetTitle({title})" ) ;
Title = title ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the native window <see cref="PhotinoWindow.Top"/> (Y) coordinate in pixels.
/// Default is 0.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <seealso cref="UseOsDefaultLocation"/>
/// <param name="top">Position in pixels from the top (Y).</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetTop ( int top )
{
Log ( $".SetTop({top})" ) ;
Top = top ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets whether the native window is always at the top of the z-order.
/// Default is false.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="topMost">Whether the window is at the top</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetTopMost ( bool topMost )
{
Log ( $".SetTopMost({topMost})" ) ;
Topmost = topMost ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the native window width in pixels.
/// Default is 0.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <seealso cref="UseOsDefaultSize"/>
/// <param name="width">Width in pixels</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetWidth ( int width )
{
Log ( $".SetWidth({width})" ) ;
Width = width ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Sets the native browser control <see cref="PhotinoWindow.Zoom"/>.
/// Default is 100.
/// </summary>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="zoom">Zoomlevel as integer</param>
/// <example>100 = 100%, 50 = 50%</example>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetZoom ( int zoom )
{
Log ( $".SetZoom({zoom})" ) ;
Zoom = zoom ;
return this ;
}
2021-06-25 13:54:01 -06:00
2025-10-18 22:30:37 -05:00
public PhotinoWindow SetFlash ( bool state )
{
Log ( $".SetFlash({state})" ) ;
Invoke ( ( ) = > Photino_SetFlash ( _nativeInstance , state ) ) ;
return this ;
}
public PhotinoWindow SetProgress ( ulong current , ulong total , PhotinoWindowProgressState state )
{
Log ( $".SetProgress({current}, {total}, {state})" ) ;
Invoke ( ( ) = > Photino_SetProgress ( _nativeInstance , current , total , state ) ) ;
return this ;
}
public PhotinoWindow ClearProgress ( )
{
Log ( $".ClearProgress()" ) ;
Invoke ( ( ) = > Photino_ClearProgress ( _nativeInstance ) ) ;
return this ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true the native window starts up at the OS Default location.
/// Default is true.
/// </summary>
/// <remarks>
/// Overrides <see cref="PhotinoWindow.Left"/> (X) and <see cref="PhotinoWindow.Top"/> (Y) properties.
/// </remarks>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="useOsDefault">Whether the OS Default should be used.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetUseOsDefaultLocation ( bool useOsDefault )
{
Log ( $".SetUseOsDefaultLocation({useOsDefault})" ) ;
UseOsDefaultLocation = useOsDefault ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// When true the native window starts at the OS Default size.
/// Default is true.
/// </summary>
/// <remarks>
/// Overrides <see cref="PhotinoWindow.Height"/> and <see cref="PhotinoWindow.Width"/> properties.
/// </remarks>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <param name="useOsDefault">Whether the OS Default should be used.</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow SetUseOsDefaultSize ( bool useOsDefault )
{
Log ( $".SetUseOsDefaultSize({useOsDefault})" ) ;
UseOsDefaultSize = useOsDefault ;
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Set runtime path for WebView2 so that developers can use Photino on Windows using the "Fixed Version" deployment module of the WebView2 runtime.
/// </summary>
/// <remarks>
/// This only works on Windows.
/// </remarks>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
/// <seealso href="https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution" />
/// <param name="data">Runtime path for WebView2</param>
2022-09-14 12:39:23 -05:00
public PhotinoWindow Win32SetWebView2Path ( string data )
{
if ( IsWindowsPlatform )
Invoke ( ( ) = > Photino_setWebView2RuntimePath_win32 ( _nativeType , data ) ) ;
else
Log ( "Win32SetWebView2Path is only supported on the Windows platform" ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
return this ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Clears the auto-fill data in the browser control.
/// </summary>
/// <remarks>
/// This method is only supported on the Windows platform.
/// </remarks>
/// <returns>
/// Returns the current <see cref="PhotinoWindow"/> instance.
/// </returns>
2023-01-21 17:20:33 -06:00
public PhotinoWindow ClearBrowserAutoFill ( )
{
if ( IsWindowsPlatform )
Invoke ( ( ) = > Photino_ClearBrowserAutoFill ( _nativeInstance ) ) ;
else
Log ( "ClearBrowserAutoFill is only supported on the Windows platform" ) ;
return this ;
}
2022-09-14 12:39:23 -05:00
//NON-FLUENT METHODS - CAN ONLY BE CALLED AFTER WINDOW IS INITIALIZED
//ONE OF THESE 2 METHODS *MUST* BE CALLED TO CREATE THE WINDOW
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
2023-07-07 23:02:00 +02:00
/// Responsible for the initialization of the primary native window and remains in operation until the window is closed.
2023-07-07 22:44:17 +02:00
/// This method is also applicable for initializing child windows, but in this case, it does not inhibit operation.
/// </summary>
2023-07-07 23:02:00 +02:00
/// <remarks>
/// The operation of the message loop is exclusive to the main native window only.
/// </remarks>
2022-09-14 12:39:23 -05:00
public void WaitForClose ( )
{
//fill in the fixed size array of custom scheme names
var i = 0 ;
foreach ( var name in CustomSchemes . Take ( 16 ) )
2021-06-25 13:54:01 -06:00
{
2024-08-30 11:38:25 -06:00
_startupParameters . CustomSchemeNames [ i ] = name . Key ;
2022-09-14 12:39:23 -05:00
i + + ;
2021-10-26 18:29:38 -07:00
}
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
_startupParameters . NativeParent = _dotNetParent = = null
? IntPtr . Zero
: _dotNetParent . _nativeInstance ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
var errors = _startupParameters . GetParamErrors ( ) ;
if ( errors . Count = = 0 )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
OnWindowCreating ( ) ;
try //All C++ exceptions will bubble up to here.
2021-06-25 13:54:01 -06:00
{
2024-12-05 10:31:39 -07:00
_nativeType = NativeLibrary . GetMainProgramHandle ( ) ;
2025-01-17 13:26:29 -07:00
2024-12-05 10:31:39 -07:00
if ( IsWindowsPlatform )
Invoke ( ( ) = > Photino_register_win32 ( _nativeType ) ) ;
else if ( IsMacOsPlatform )
Invoke ( ( ) = > Photino_register_mac ( ) ) ;
2022-09-14 12:39:23 -05:00
Invoke ( ( ) = > _nativeInstance = Photino_ctor ( ref _startupParameters ) ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
catch ( Exception ex )
{
int lastError = 0 ;
if ( IsWindowsPlatform )
lastError = Marshal . GetLastWin32Error ( ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
Log ( $"***\n{ex.Message}\n{ex.StackTrace}\nError #{lastError}" ) ;
throw new ApplicationException ( $"Native code exception. Error # {lastError} See inner exception for details." , ex ) ;
}
OnWindowCreated ( ) ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
if ( ! _messageLoopIsStarted )
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
_messageLoopIsStarted = true ;
try
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
Invoke ( ( ) = > Photino_WaitForExit ( _nativeInstance ) ) ; //start the message loop. there can only be 1 message loop for all windows.
2021-06-25 13:54:01 -06:00
}
catch ( Exception ex )
{
int lastError = 0 ;
if ( IsWindowsPlatform )
lastError = Marshal . GetLastWin32Error ( ) ;
Log ( $"***\n{ex.Message}\n{ex.StackTrace}\nError #{lastError}" ) ;
throw new ApplicationException ( $"Native code exception. Error # {lastError} See inner exception for details." , ex ) ;
}
}
}
2022-09-14 12:39:23 -05:00
else
2021-06-25 13:54:01 -06:00
{
2022-09-14 12:39:23 -05:00
var formattedErrors = "\n" ;
foreach ( var error in errors )
formattedErrors + = error + "\n" ;
2021-06-25 13:54:01 -06:00
2022-09-14 12:39:23 -05:00
throw new ArgumentException ( $"Startup Parameters Are Not Valid: {formattedErrors}" ) ;
2021-06-25 13:54:01 -06:00
}
2022-09-14 12:39:23 -05:00
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Closes the native window.
/// </summary>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
2022-09-14 12:39:23 -05:00
public void Close ( )
{
Log ( ".Close()" ) ;
if ( _nativeInstance = = IntPtr . Zero )
throw new ApplicationException ( "Close cannot be called until after the Photino window is initialized." ) ;
Invoke ( ( ) = > Photino_Close ( _nativeInstance ) ) ;
}
2021-06-25 13:54:01 -06:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Send a message to the native window's native browser control's JavaScript context.
/// </summary>
/// <remarks>
/// In JavaScript, messages can be received via <code>window.external.receiveMessage(message)</code>
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
/// <param name="message">Message as string</param>
2022-09-14 12:39:23 -05:00
public void SendWebMessage ( string message )
{
Log ( $".SendWebMessage({message})" ) ;
if ( _nativeInstance = = IntPtr . Zero )
throw new ApplicationException ( "SendWebMessage cannot be called until after the Photino window is initialized." ) ;
Invoke ( ( ) = > Photino_SendWebMessage ( _nativeInstance , message ) ) ;
}
2021-06-25 13:54:01 -06:00
2023-09-14 12:40:08 -05:00
public async Task SendWebMessageAsync ( string message )
{
await Task . Run ( ( ) = >
{
Log ( $".SendWebMessage({message})" ) ;
if ( _nativeInstance = = IntPtr . Zero )
throw new ApplicationException ( "SendWebMessage cannot be called until after the Photino window is initialized." ) ;
Invoke ( ( ) = > Photino_SendWebMessage ( _nativeInstance , message ) ) ;
} ) ;
}
2025-10-18 21:03:44 -05:00
/// <summary>
/// Start dragging the window as if the title bar was being clicked on
/// </summary>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
public void StartDragging ( )
{
Log ( $".StartDragging()" ) ;
if ( _nativeInstance = = IntPtr . Zero )
throw new ApplicationException ( "StartDragging cannot be called until after the Photino window is initialized." ) ;
Invoke ( ( ) = > Photino_StartDragging ( _nativeInstance ) ) ;
}
/// <summary>
/// Start resizing the window as if an edge/corner was being clicked on
/// </summary>
/// <param name="hitTestCode">The edge/corner where the resizing should start</param>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
public void StartResizing ( PhotinoWindowHitTestCode hitTestCode )
{
Log ( $".StartResizing({hitTestCode})" ) ;
if ( _nativeInstance = = IntPtr . Zero )
throw new ApplicationException ( "StartResizing cannot be called until after the Photino window is initialized." ) ;
Invoke ( ( ) = > Photino_StartResizing ( _nativeInstance , hitTestCode ) ) ;
}
2025-10-18 19:12:02 -05:00
public PhotinoNotification CreateNotification ( PhotinoNotificationType type )
2022-09-14 12:39:23 -05:00
{
2025-10-18 19:12:02 -05:00
Log ( $".Createnotification({type})" ) ;
2022-09-14 12:39:23 -05:00
if ( _nativeInstance = = IntPtr . Zero )
2025-10-18 19:12:02 -05:00
throw new ApplicationException ( "CreateNotification cannot be called until after the Photino window is initialized." ) ;
return new PhotinoNotification ( _nativeInstance )
. SetType ( type ) ;
2025-09-06 22:16:59 -05:00
}
2023-02-22 14:02:45 -05:00
/// <summary>
2023-07-07 22:44:17 +02:00
/// Show an open file dialog native to the OS.
2023-02-22 14:02:45 -05:00
/// </summary>
2023-07-07 22:44:17 +02:00
/// <remarks>
2024-10-17 13:46:43 -06:00
/// Filter names are not used on macOS. Use async version for Photino.Blazor as syncronous version crashes.
2023-07-07 22:44:17 +02:00
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
/// <param name="title">Title of the dialog</param>
/// <param name="defaultPath">Default path. Defaults to <see cref="Environment.SpecialFolder.MyDocuments"/></param>
/// <param name="multiSelect">Whether multiple selections are allowed</param>
/// <param name="filters">Array of <see cref="Extensions"/> for filtering.</param>
/// <returns>Array of file paths as strings</returns>
2023-02-22 14:02:45 -05:00
public string [ ] ShowOpenFile ( string title = "Choose file" , string defaultPath = null , bool multiSelect = false , ( string Name , string [ ] Extensions ) [ ] filters = null ) = > ShowOpenDialog ( false , title , defaultPath , multiSelect , filters ) ;
2023-08-24 12:19:10 -06:00
2024-10-17 13:46:43 -06:00
/// <summary>
/// Async version is required for Photino.Blazor
/// </summary>
/// <remarks>
/// Filter names are not used on macOS. Use async version for Photino.Blazor as syncronous version crashes.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
/// <param name="title">Title of the dialog</param>
/// <param name="defaultPath">Default path. Defaults to <see cref="Environment.SpecialFolder.MyDocuments"/></param>
/// <param name="multiSelect">Whether multiple selections are allowed</param>
/// <param name="filters">Array of <see cref="Extensions"/> for filtering.</param>
/// <returns>Array of file paths as strings</returns>
public async Task < string [ ] > ShowOpenFileAsync ( string title = "Choose file" , string defaultPath = null , bool multiSelect = false , ( string Name , string [ ] Extensions ) [ ] filters = null )
{
return await Task . Run ( ( ) = > ShowOpenFile ( title , defaultPath , multiSelect , filters ) ) ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Show an open folder dialog native to the OS.
/// </summary>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
/// <param name="title">Title of the dialog</param>
/// <param name="defaultPath">Default path. Defaults to <see cref="Environment.SpecialFolder.MyDocuments"/></param>
/// <param name="multiSelect">Whether multiple selections are allowed</param>
/// <returns>Array of folder paths as strings</returns>
2023-02-22 14:02:45 -05:00
public string [ ] ShowOpenFolder ( string title = "Select folder" , string defaultPath = null , bool multiSelect = false ) = > ShowOpenDialog ( true , title , defaultPath , multiSelect , null ) ;
2024-10-17 13:46:43 -06:00
/// <summary>
/// Async version is required for Photino.Blazor
/// </summary>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
/// <param name="title">Title of the dialog</param>
/// <param name="defaultPath">Default path. Defaults to <see cref="Environment.SpecialFolder.MyDocuments"/></param>
/// <param name="multiSelect">Whether multiple selections are allowed</param>
/// <returns>Array of folder paths as strings</returns>
public async Task < string [ ] > ShowOpenFolderAsync ( string title = "Choose file" , string defaultPath = null , bool multiSelect = false )
{
return await Task . Run ( ( ) = > ShowOpenFolder ( title , defaultPath , multiSelect ) ) ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Show an save folder dialog native to the OS.
2023-02-22 14:02:45 -05:00
/// </summary>
2023-07-07 22:44:17 +02:00
/// <remarks>
/// Filter names are not used on macOS.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
/// <param name="title">Title of the dialog</param>
/// <param name="defaultPath">Default path. Defaults to <see cref="Environment.SpecialFolder.MyDocuments"/></param>
/// <param name="filters">Array of <see cref="Extensions"/> for filtering.</param>
/// <returns></returns>
2025-08-18 12:09:51 -06:00
public string ShowSaveFile ( string title = "Save file" , string defaultPath = null , ( string Name , string [ ] Extensions ) [ ] filters = null , string defaultFileName = null )
2023-02-22 14:02:45 -05:00
{
defaultPath ? ? = Environment . GetFolderPath ( Environment . SpecialFolder . MyDocuments ) ;
filters ? ? = Array . Empty < ( string , string [ ] ) > ( ) ;
2025-08-18 12:09:51 -06:00
defaultFileName ? ? = string . Empty ;
2023-02-22 14:02:45 -05:00
string result = null ;
var nativeFilters = GetNativeFilters ( filters ) ;
2023-08-24 12:19:10 -06:00
Invoke ( ( ) = >
{
2025-08-18 12:09:51 -06:00
var ptrResult = Photino_ShowSaveFile ( _nativeInstance , title , defaultPath , nativeFilters , filters . Length , defaultFileName ) ;
2023-02-22 14:02:45 -05:00
result = Marshal . PtrToStringAuto ( ptrResult ) ;
} ) ;
return result ;
}
2024-10-17 13:46:43 -06:00
/// <summary>
/// Async version is required for Photino.Blazor
/// </summary>
/// <remarks>
/// Filter names are not used on macOS.
/// </remarks>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
/// <param name="title">Title of the dialog</param>
/// <param name="defaultPath">Default path. Defaults to <see cref="Environment.SpecialFolder.MyDocuments"/></param>
/// <param name="filters">Array of <see cref="Extensions"/> for filtering.</param>
/// <returns></returns>
2025-08-18 12:09:51 -06:00
public async Task < string > ShowSaveFileAsync ( string title = "Choose file" , string defaultPath = null , ( string Name , string [ ] Extensions ) [ ] filters = null , string defaultFileName = null )
2024-10-17 13:46:43 -06:00
{
2025-08-18 12:09:51 -06:00
return await Task . Run ( ( ) = > ShowSaveFile ( title , defaultPath , filters , defaultFileName ) ) ;
2024-10-17 13:46:43 -06:00
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Show a message dialog native to the OS.
/// </summary>
/// <exception cref="ApplicationException">
/// Thrown when the window is not initialized.
/// </exception>
/// <param name="title">Title of the dialog</param>
/// <param name="text">Text of the dialog</param>
/// <param name="buttons">Available interaction buttons <see cref="PhotinoDialogButtons"/></param>
/// <param name="icon">Icon of the dialog <see cref="PhotinoDialogButtons"/></param>
/// <returns><see cref="PhotinoDialogResult" /></returns>
2023-02-22 14:02:45 -05:00
public PhotinoDialogResult ShowMessage ( string title , string text , PhotinoDialogButtons buttons = PhotinoDialogButtons . Ok , PhotinoDialogIcon icon = PhotinoDialogIcon . Info )
{
var result = PhotinoDialogResult . Cancel ;
Invoke ( ( ) = > result = Photino_ShowMessage ( _nativeInstance , title , text , buttons , icon ) ) ;
return result ;
}
2023-07-07 22:44:17 +02:00
/// <summary>
/// Show a native open dialog.
/// </summary>
/// <param name="foldersOnly">Whether files are hidden</param>
/// <param name="title">Title of the dialog</param>
/// <param name="defaultPath">Default path. Defaults to <see cref="Environment.SpecialFolder.MyDocuments"/></param>
/// <param name="multiSelect">Whether multiple selections are allowed</param>
/// <param name="filters">Array of <see cref="Extensions"/> for filtering.</param>
/// <returns>Array of paths</returns>
2023-02-22 14:02:45 -05:00
private string [ ] ShowOpenDialog ( bool foldersOnly , string title , string defaultPath , bool multiSelect , ( string Name , string [ ] Extensions ) [ ] filters )
{
defaultPath ? ? = Environment . GetFolderPath ( Environment . SpecialFolder . MyDocuments ) ;
filters ? ? = Array . Empty < ( string , string [ ] ) > ( ) ;
var results = Array . Empty < string > ( ) ;
var nativeFilters = GetNativeFilters ( filters , foldersOnly ) ;
2023-08-24 12:19:10 -06:00
Invoke ( ( ) = >
{
var ptrResults = foldersOnly ?
2023-02-22 14:02:45 -05:00
Photino_ShowOpenFolder ( _nativeInstance , title , defaultPath , multiSelect , out var resultCount ) :
Photino_ShowOpenFile ( _nativeInstance , title , defaultPath , multiSelect , nativeFilters , nativeFilters . Length , out resultCount ) ;
if ( resultCount = = 0 ) return ;
var ptrArray = new IntPtr [ resultCount ] ;
results = new string [ resultCount ] ;
Marshal . Copy ( ptrResults , ptrArray , 0 , resultCount ) ;
for ( var i = 0 ; i < resultCount ; i + + )
{
results [ i ] = Marshal . PtrToStringAuto ( ptrArray [ i ] ) ;
}
} ) ;
return results ;
}
2022-09-14 12:39:23 -05:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Logs a message.
/// </summary>
/// <param name="message">Log message</param>
2022-09-14 12:39:23 -05:00
private void Log ( string message )
{
if ( LogVerbosity < 1 ) return ;
Console . WriteLine ( $"Photino.NET: \" { Title ? ? "PhotinoWindow" } \ "{message}" ) ;
2021-06-25 13:54:01 -06:00
}
2023-02-22 14:02:45 -05:00
2023-07-07 22:44:17 +02:00
/// <summary>
/// Returns an array of strings for native filters
/// </summary>
/// <param name="filters"></param>
/// <param name="empty"></param>
/// <returns>String array of filters</returns>
2023-02-22 14:02:45 -05:00
private static string [ ] GetNativeFilters ( ( string Name , string [ ] Extensions ) [ ] filters , bool empty = false )
{
var nativeFilters = Array . Empty < string > ( ) ;
if ( ! empty & & filters is { Length : > 0 } )
{
nativeFilters = IsMacOsPlatform ?
filters . SelectMany ( t = > t . Extensions . Select ( s = > s = = "*" ? s : s . TrimStart ( '*' , '.' ) ) ) . ToArray ( ) :
filters . Select ( t = > $"{t.Name}|{t.Extensions.Select(s => s.StartsWith('.') ? $" * { s } " : !s.StartsWith(" * . ") ? $" * . { s } " : s).Aggregate((e1, e2) => $" { e1 } ; { e2 } ")}" ) . ToArray ( ) ;
}
return nativeFilters ;
}
2025-03-14 23:17:11 -04:00
/// <summary>
/// Extracts an embedded resource from the assembly to a temporary file.
/// </summary>
/// <remarks>
/// The resource is expected to be located within the provided namespace and under the `wwwroot` folder.
/// This method will write the resource to a temporary file and return its path.
/// </remarks>
/// <returns>
/// The path to the temporary file containing the extracted resource, or <c>null</c> if the resource was not found.
/// </returns>
/// <param name="fileName">The name of the embedded resource file (e.g., "favicon.ico").</param>
/// <param name="resourceNamespace">
/// The namespace where the embedded resource is located (e.g., "MyApp" or "MyCompany.MyApp").
///
/// The method expects the resource to be in the `wwwroot` folder of the provided namespace.
/// </param>
private string ExtractEmbeddedResourceToTempFile ( string fileName , string resourceNamespace )
{
string resourceName = $"{resourceNamespace}.wwwroot.{fileName}" ;
Assembly assembly = Assembly . GetExecutingAssembly ( ) ;
2023-08-24 12:19:10 -06:00
2025-03-14 23:17:11 -04:00
using ( Stream resourceStream = assembly . GetManifestResourceStream ( resourceName ) )
{
if ( resourceStream = = null )
{
Log ( $"Resource '{fileName}' couldn't be found in namespace '{resourceNamespace}'" ) ;
return null ;
}
string tempFile = Path . Combine ( Path . GetTempPath ( ) , fileName ) ;
using ( FileStream fileStream = new FileStream ( tempFile , FileMode . Create , FileAccess . Write ) )
{
resourceStream . CopyTo ( fileStream ) ;
}
return tempFile ;
}
}
2021-10-26 18:29:38 -07:00
}