Is it possible to create ahref link in a pop up window or is it possible to support html tag ahref in a popup window
What I want to achieve is when user clicks on a game object a model popup will be displayed and on that model pop story title and story link will be displayed as a list and when user clicks on any of the link, it must open the url in a browser window.
I tried this modal but ahref not working in this popup
using UnityEngine;
using System;
// example:
// HFTDialog.MessageBox("error", "Sorry but you're S.O.L", () => { Application.Quit() });
public class HFTDialog : MonoBehaviour {
Rect m_windowRect;
Action m_action;
string m_title;
string m_msg;
static public void MessageBox(string title, string msg, Action action)
{
GameObject go = new GameObject("HFTDialog");
HFTDialog dlg = go.AddComponent<HFTDialog>();
dlg.Init(title, msg, action);
}
static public void CloseMessageBox(GameObject go)
{
Destroy(go.gameObject);
}
void Init(string title, string msg, Action action)
{
m_title = title;
m_msg = msg;
m_action = action;
}
void OnGUI()
{
const int maxWidth = 640;
const int maxHeight = 480;
int width = Mathf.Min(maxWidth, Screen.width - 20);
int height = Mathf.Min(maxHeight, Screen.height - 20);
m_windowRect = new Rect(
(Screen.width - width) / 2,
(Screen.height - height) / 2,
width,
height);
m_windowRect = GUI.Window(0, m_windowRect, WindowFunc, m_title);
}
void WindowFunc(int windowID)
{
const int border = 10;
const int width = 50;
const int height = 25;
const int spacing = 10;
Rect l = new Rect(
border,
border + spacing,
m_windowRect.width - border * 2,
m_windowRect.height - border * 2 - height - spacing);
GUI.Label(l, m_msg);
Rect b = new Rect(
m_windowRect.width - width - border,
m_windowRect.height - height - border,
width,
height);
if (GUI.Button(b, "close"))
{
Destroy(this.gameObject);
m_action();
}
}
}
Related
I just start learning WinUI 3.0 and can't find any information in google or books like Learn WinUI 3.0 how to set default window size of application. I know in UWP it can be like
ApplicationView.PreferredLaunchViewSize = new Size(480, 800);
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
But actually it doesn't work in WinUI
No need to do these interop calls on your own or use third-party packages for this.
Try this trifecta:
// Use 'this' rather than 'window' as variable if this is about the current window.
IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
Then you can finally set the size with:
appWindow.Resize(new Windows.Graphics.SizeInt32 { Width = 480, Height = 800 });
Note that an AppWindow object has several other functions as well, like
MoveAndResize, Show, Hide, and features to modify the title bar.
Take a look at this repository dotMorten/WinUIEx.
It contains a method to set the window size and position
myWindow.SetWindowPositionAndSize(100, 100, 1024, 768);
I also found an example in the WinUI3 Samples
I'm adding the relevant code here for easy reference
private void SetWindowSize(IntPtr hwnd, int width, int height)
{
var dpi = PInvoke.User32.GetDpiForWindow(hwnd);
float scalingFactor = (float)dpi / 96;
width = (int)(width * scalingFactor);
height = (int)(height * scalingFactor);
PInvoke.User32.SetWindowPos(hwnd, PInvoke.User32.SpecialWindowHandles.HWND_TOP,
0, 0, width, height,
PInvoke.User32.SetWindowPosFlags.SWP_NOMOVE);
}
I can't comment on answers yet but to add to Jonas' answer, you can put his answer in the class constructor (where this.InitializeComponent() is) of your main window code-behind or in the OnLaunched method of App.cs. I'm sure that seems obvious to a lot of people but to those coming from other languages/platforms it might not be. Example:
public MainWindow()
{
this.InitializeComponent();
IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this); // m_window in App.cs
WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd);
AppWindow appWindow = AppWindow.GetFromWindowId(windowId);
var size = new Windows.Graphics.SizeInt32();
size.Width = 480;
size.Height = 800;
appWindow.Resize(size);
// or like Jonas said:
// appWindow.Resize(new Windows.Graphics.SizeInt32 { Width = 480, Height = 800 });
}
This works. You will need to add the nuget package PInvoke.User32.
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
m_window = new MainWindow();
m_window.Activate();
//Get the Window's HWND
var windowNative = m_window.As<IWindowNative>();
m_windowHandle = windowNative.WindowHandle;
m_window.Activate();
SetWindowBounds(0,0,100,100);
}
private Window m_window;
private IntPtr m_windowHandle;
public IntPtr WindowHandle { get { return m_windowHandle; } }
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("EECDBF0E-BAE9-4CB6-A68E-9598E1CB57BB")]
internal interface IWindowNative
{
IntPtr WindowHandle { get; }
}
public void SetWindowBounds(int x, int y, int width, int height)
{
var dpi = PInvoke.User32.GetDpiForWindow(m_windowHandle);
float scalingFactor = (float)dpi / 96;
width = (int)(width * scalingFactor);
height = (int)(height * scalingFactor);
PInvoke.User32.SetWindowPos(m_windowHandle, PInvoke.User32.SpecialWindowHandles.HWND_TOP,
x, y, width, height,
PInvoke.User32.SetWindowPosFlags.SWP_NOMOVE);
}
Goal is to create DateTimePicker similar to the screen shot of this question.
First attempt overriding OnPaint:
public class MyDateTimePicker : DateTimePicker
{
private Image _image;
public MyDateTimePicker() : base()
{
SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw |
ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
}
[Browsable(true)]
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
base.BackColor = value;
}
}
[Category("Appearance")]
public Color BorderColor { get; set; } = Color.Black;
[Category("Appearance")]
public Color TextColor { get; set; } = Color.Black;
[Category("Appearance")]
public Image Image
{
get
{
return _image;
}
set
{
_image = value;
Invalidate();
}
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
// Fill the Background
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), 0, 0, ClientRectangle.Width, ClientRectangle.Height);
// Draw DateTime text
e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(TextColor), 5, 2);
// Draw Icon
if (_image != null)
{
Rectangle im_rect = new Rectangle(ClientRectangle.Width - 20, 2, ClientRectangle.Height - 4, ClientRectangle.Height - 4);
e.Graphics.DrawImage(_image, im_rect);
}
// Draw Border
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(0, 0, ClientRectangle.Width - 1, ClientRectangle.Height - 1));
}
}
This solution has the following issues: date fields are not clickable, text artifacts when changing date with arrow keys, narrow clickable area of the button.
Second solution overriding WndProc:
public class MyDateTimePicker : DateTimePicker
{
private const int WM_PAINT = 0x000F;
private Color _borderColor = Color.Black;
public MyDateTimePicker() { }
[Category("Appearance")]
public Color BorderColor
{
get { return _borderColor; }
set
{
if (_borderColor != value)
{
_borderColor = value;
this.Invalidate();
}
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_PAINT:
base.WndProc(ref m);
using (var g = Graphics.FromHwnd(m.HWnd))
{
var rect = new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
g.DrawRectangle(new Pen(this.BorderColor), rect);
}
m.Result = IntPtr.Zero;
break;
default:
base.WndProc(ref m);
break;
}
}
}
This solution lacks the customization of the button. Maybe anyone knows how to customize button in this way, or how to solve issues of the first solution?
Also if it is possible I would like to change the height of DateTimePicker to match height of ComboBox (currently they differ by 1px).
You can handle WM_PAINT and draw the border and button yourself. To get the accurate size of the dropdown, send DTM_GETDATETIMEPICKERINFO message.
The width of the dropdown button may vary depending to the size of the control and the space required by the text of the control:
Flat DateTimePicker
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class FlatDateTimePicker : DateTimePicker
{
public FlatDateTimePicker()
{
SetStyle(ControlStyles.ResizeRedraw |
ControlStyles.OptimizedDoubleBuffer, true);
}
private Color borderColor = Color.DeepSkyBlue;
[DefaultValue(typeof(Color), "RoyalBlue")]
public Color BorderColor
{
get { return borderColor; }
set
{
if (borderColor != value)
{
borderColor = value;
Invalidate();
}
}
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT)
{
var info = new DATETIMEPICKERINFO();
info.cbSize = Marshal.SizeOf(info);
SendMessage(Handle, DTM_GETDATETIMEPICKERINFO, IntPtr.Zero, ref info);
using (var g = Graphics.FromHwndInternal(Handle))
{
var clientRect = new Rectangle(0,0,Width, Height);
var buttonWidth = info.rcButton.R - info.rcButton.L;
var dropDownRect = new Rectangle(info.rcButton.L, info.rcButton.T,
buttonWidth, clientRect.Height);
if (RightToLeft == RightToLeft.Yes && RightToLeftLayout == true)
{
dropDownRect.X = clientRect.Width - dropDownRect.Right;
dropDownRect.Width += 1;
}
var middle = new Point(dropDownRect.Left + dropDownRect.Width / 2,
dropDownRect.Top + dropDownRect.Height / 2);
var arrow = new Point[]
{
new Point(middle.X - 3, middle.Y - 2),
new Point(middle.X + 4, middle.Y - 2),
new Point(middle.X, middle.Y + 2)
};
var borderAndButtonColor = Enabled ? BorderColor : Color.LightGray;
var arrorColor = BackColor;
using (var pen = new Pen(borderAndButtonColor))
g.DrawRectangle(pen, 0, 0,
clientRect.Width - 1, clientRect.Height - 1);
using (var brush = new SolidBrush(borderAndButtonColor))
g.FillRectangle(brush, dropDownRect);
g.FillPolygon(Brushes.Black, arrow);
}
}
}
const int WM_PAINT = 0xF;
const int DTM_FIRST = 0x1000;
const int DTM_GETDATETIMEPICKERINFO = DTM_FIRST + 14;
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
IntPtr wParam, ref DATETIMEPICKERINFO info);
[StructLayout(LayoutKind.Sequential)]
struct RECT
{
public int L, T, R, B;
}
[StructLayout(LayoutKind.Sequential)]
struct DATETIMEPICKERINFO
{
public int cbSize;
public RECT rcCheck;
public int stateCheck;
public RECT rcButton;
public int stateButton;
public IntPtr hwndEdit;
public IntPtr hwndUD;
public IntPtr hwndDropDown;
}
}
Clone or Download Extended version
I have created an extended version of this answer, which supports rendering the up-down button and the checkbox in flat style, also highlighting the arrow on mouse move, something like this:
You can download or close the code:
r-aghaei/FlatDateTimePickerExample
master.zip
Related Posts
You may also want to take a look at the following flat style controls:
Flat TextBox - Change border color of TextBox
Flat ComboBox - Change border color and dropdown button of ComboBox
Flat NumericUpDown - Change border color and spin buttons of NumericUpDown
I'm trying to change the span of CollectionView while rotating my iPhone. To make it easy, just show 2 columns in portrait, and 4 columns in landscape.
It works when rotating from portrait to landscape mode, but when rotating back to portrait mode, it always shows 1 column. My code likes,
VideoCollectionView = new CollectionView()
{
ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical),
};
...
private static double screen_width = 1280.0;
private static double screen_height = 720.0;
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if ((Math.Abs(screen_width - width) > minimum_double) || (Math.Abs(screen_height - height) > minimum_double))
{
screen_width = width;
screen_height = height;
int split;
if (screen_width > screen_height)
{ // landscape mode
split = 4;
}
else
{ // portrait mode
split = 2;
}
VideoCollectionView.ItemsLayout = new GridItemsLayout(split, ItemsLayoutOrientation.Vertical);
}
}
Is this a bug? Or I should use other ways? Thanks for help.
You could use a Singleton for storing the current orientation.Because it is unwise to set the screen size as s static value . It maybe will cause issue on different size of device .
public class CurrentDevice
{
protected static CurrentDevice Instance;
double width;
double height;
static CurrentDevice()
{
Instance = new CurrentDevice();
}
protected CurrentDevice()
{
}
public static bool IsOrientationPortrait()
{
return Instance.height > Instance.width;
}
public static void SetSize(double width, double height)
{
Instance.width = width;
Instance.height = height;
}
}
And in the method
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if (CurrentDevice.IsOrientationPortrait() && width > height || !CurrentDevice.IsOrientationPortrait() && width < height)
{
int split;
CurrentDevice.SetSize(width, height);
// Orientation got changed! Do your changes here
if (CurrentDevice.IsOrientationPortrait())
{
// portrait mode
split = 2;
}
else
{
// landscape mode
split = 4;
}
VideoCollectionView.ItemsLayout = new GridItemsLayout(split, ItemsLayoutOrientation.Vertical);
}
}
I have made dependency services on both side and Interface in shared library on Xamarin platform
when i use it in xaml.cs hard coded it works but when i use it in ViewModel using messaging center to set count of notification in Toolbar of application it doesn't works
Does anyone have any kind of idea whats happening or should i do ?
this code works from Xaml.cs page
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, ToolbarItems[0], "2", Color.Red, Color.White);
And Below Code doesn't works
From ViewModel
" MessagingCenter.Send(new MessagingCenterModel { }, "NotificationCount", NotificationListCount);
At Xaml.cs Page
MessagingCenter.Subscribe<MessagingCenterModel, string>(this, "NotificationCount", (sender, args) =>
{
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, ToolbarItems[0], args, Color.Red, Color.White);
});
InterFaceCode
public interface IToolbarItemBadgeService
{
void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor);
}
Dependency service
public class ToolbarItemBadgeService : IToolbarItemBadgeService
{
public void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor)
{
Device.BeginInvokeOnMainThread(() =>
{
var toolbar = CrossCurrentActivity.Current.Activity.FindViewById(Resource.Id.toolbar) as Android.Support.V7.Widget.Toolbar;
if (toolbar != null)
{
if (!string.IsNullOrEmpty(value))
{
var idx = page.ToolbarItems.IndexOf(item);
if (toolbar.Menu.Size() > idx)
{
var menuItem = toolbar.Menu.GetItem(idx);
BadgeDrawable.SetBadgeText(CrossCurrentActivity.Current.Activity, menuItem, value, backgroundColor.ToAndroid(), textColor.ToAndroid());
}
}
}
});
}
}
BadgeDrawable Class
public class BadgeDrawable : Drawable
{
private const string BadgeValueOverflow = "*";
private Paint _badgeBackground;
private Paint _badgeText;
private Rect _textRect = new Rect();
private string _badgeValue = "";
private bool _shouldDraw = true;
Context _context;
public override int Opacity => (int)Format.Unknown;
public BadgeDrawable(Context context, Color backgroundColor, Color textColor)
{
_context = context;
float textSize = context.Resources.GetDimension(Resource.Dimension.textsize_badge_count);
_badgeBackground = new Paint();
_badgeBackground.Color = backgroundColor;
_badgeBackground.AntiAlias = true;
_badgeBackground.SetStyle(Paint.Style.Fill);
_badgeText = new Paint();
_badgeText.Color = textColor;
_badgeText.SetTypeface(Typeface.Default);
_badgeText.TextSize = textSize;
_badgeText.AntiAlias = true;
_badgeText.TextAlign = Paint.Align.Center;
}
public override void Draw(Canvas canvas)
{
if (!_shouldDraw)
{
return;
}
Rect bounds = Bounds;
float width = bounds.Right - bounds.Left;
float height = bounds.Bottom - bounds.Top;
float oneDp = 1 * _context.Resources.DisplayMetrics.Density;
// Position the badge in the top-right quadrant of the icon.
float radius = ((Java.Lang.Math.Max(width, height) / 2)) / 2;
float centerX = (width - radius - 1) + oneDp * 2;
float centerY = radius - 2 * oneDp;
canvas.DrawCircle(centerX, centerY, (int)(radius + oneDp * 5), _badgeBackground);
// Draw badge count message inside the circle.
_badgeText.GetTextBounds(_badgeValue, 0, _badgeValue.Length, _textRect);
float textHeight = _textRect.Bottom - _textRect.Top;
float textY = centerY + (textHeight / 2f);
canvas.DrawText(_badgeValue.Length > 2 ? BadgeValueOverflow : _badgeValue,
centerX, textY, _badgeText);
}
// Sets the text to display. Badge displays a '*' if more than 2 characters
private void SetBadgeText(string text)
{
_badgeValue = text;
// Only draw a badge if the value isn't a zero
_shouldDraw = !text.Equals("0");
InvalidateSelf();
}
public override void SetAlpha(int alpha)
{
// do nothing
}
public override void SetColorFilter(ColorFilter cf)
{
// do nothing
}
public static void SetBadgeCount(Context context, IMenuItem item, int count, Color backgroundColor, Color textColor)
{
SetBadgeText(context, item, $"{count}", backgroundColor, textColor);
}
public static void SetBadgeText(Context context, IMenuItem item, string text, Color backgroundColor, Color textColor)
{
if (item.Icon == null)
{
return;
}
BadgeDrawable badge = null;
Drawable icon = item.Icon;
if (item.Icon is LayerDrawable)
{
LayerDrawable lDrawable = item.Icon as LayerDrawable;
if (string.IsNullOrEmpty(text) || text == "0")
{
icon = lDrawable.GetDrawable(0);
lDrawable.Dispose();
}
else
{
for (var i = 0; i < lDrawable.NumberOfLayers; i++)
{
if (lDrawable.GetDrawable(i) is BadgeDrawable)
{
badge = lDrawable.GetDrawable(i) as BadgeDrawable;
break;
}
}
if (badge == null)
{
badge = new BadgeDrawable(context, backgroundColor, textColor);
icon = new LayerDrawable(new Drawable[] { item.Icon, badge });
}
}
}
else
{
badge = new BadgeDrawable(context, backgroundColor, textColor);
icon = new LayerDrawable(new Drawable[] { item.Icon, badge });
}
badge?.SetBadgeText(text);
item.SetIcon(icon);
icon.Dispose();
}
}
Firstly , make sure that we had Subscribe the message before we send it . Otherwise the codes in Subscribe will never been called .
In addition , the code in Dependency Service could only set the badge of ToolbarItem in the navigation bar (on tabbed bar it will never work).
If you want to set the badge of tabbed page icon , you could use the plugin Plugin.Badge .
how to create a modal pop up with html support ie with a href link ( links must be clickable ) in unity. I want to create a popup that list stores and the link , when user clicks on the story link , the link must be opened in a browser ( as the story link will contain picture and videos)
I tried this but a href links not working on this modal pop up
using UnityEngine;
using System;
// example:
// HFTDialog.MessageBox("error", "Sorry but you're S.O.L", () => { Application.Quit() });
public class HFTDialog : MonoBehaviour {
Rect m_windowRect;
Action m_action;
string m_title;
string m_msg;
static public void MessageBox(string title, string msg, Action action)
{
GameObject go = new GameObject("HFTDialog");
HFTDialog dlg = go.AddComponent<HFTDialog>();
dlg.Init(title, msg, action);
}
static public void CloseMessageBox(GameObject go)
{
Destroy(go.gameObject);
}
void Init(string title, string msg, Action action)
{
m_title = title;
m_msg = msg;
m_action = action;
}
void OnGUI()
{
const int maxWidth = 640;
const int maxHeight = 480;
int width = Mathf.Min(maxWidth, Screen.width - 20);
int height = Mathf.Min(maxHeight, Screen.height - 20);
m_windowRect = new Rect(
(Screen.width - width) / 2,
(Screen.height - height) / 2,
width,
height);
m_windowRect = GUI.Window(0, m_windowRect, WindowFunc, m_title);
}
void WindowFunc(int windowID)
{
const int border = 10;
const int width = 50;
const int height = 25;
const int spacing = 10;
Rect l = new Rect(
border,
border + spacing,
m_windowRect.width - border * 2,
m_windowRect.height - border * 2 - height - spacing);
GUI.Label(l, m_msg);
Rect b = new Rect(
m_windowRect.width - width - border,
m_windowRect.height - height - border,
width,
height);
if (GUI.Button(b, "close"))
{
Destroy(this.gameObject);
m_action();
}
}
}
I want something similar to this but ahref links must be supported in the popup