Can anybody explain me this Java code in C#, since I use Mono for Android? For example I can't find OnGlobalLayoutListener in Mono for Android.
On Android it looks like this:
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int newWidth, newHeight, oldHeight, oldWidth;
//the new width will fit the screen
newWidth = metrics.widthPixels;
//so we can scale proportionally
oldHeight = iv.getDrawable().getIntrinsicHeight();
oldWidth = iv.getDrawable().getIntrinsicWidth();
newHeight = Math.floor((oldHeight * newWidth) / oldWidth);
iv.setLayoutParams(new LinearLayout.LayoutParams(newWidth, newHeight));
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
//so this only happens once
iv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
What is the Mono for Android equivalent?
OnGlobalLayoutListener is an interface, so in C# it is exposed as ViewTreeObserver.IOnGlobalLayoutListener. Since C# doesn't support anonymous classes as seen here in Java, you would need to provide an implementation of that interface and pass that into AddOnGlobalLayoutListener():
public class MyLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
{
public void OnGlobalLayout()
{
// do stuff here
}
}
vto.AddOnGlobalLayoutListener(new MyLayoutListener());
You can do this if you want, but the preferred way in Mono for Android is to use events in place of listener interfaces. In this case, it is exposed as the GlobalLayout event:
vto.GlobalLayout += (sender, args) =>
{
// do stuff here
};
You can get an instance of the ViewTreeObserver like this:
var contentView = activity.Window.DecorView.FindViewById(Android.Resource.Id.Content);
contentView.ViewTreeObserver.GlobalLayout += ViewTreeObserverOnGlobalLayout;
Here is an information from Android Developers website :
addOnGlobalLayoutListener(ViewTreeObserver.OnGlobalLayoutListener
listener)
Register a callback to be invoked when the global layout state or the visibility of views within the view tree changes
Here is the link you can take a look : addOnGlobalLayoutListener. and here onGlobalLayoutListener
Related
I am learning C# and came across a sample code which are as follows :
Shapes.cs
using System;
public record Position(int X, int Y);
public record Size(int Width, int Height);
public abstract record Shape(Position Position, Size Size)
{
public void Draw() => DisplayShape();
protected virtual void DisplayShape()
{
Console.WriteLine($"Shape with {Position} and {Size}");
}
}
ConcreteShapes.cs
using System;
public record Rectangle(Position Position, Size Size) : Shape(Position, Size)
{
protected override void DisplayShape()
{
Console.WriteLine($"Rectangle at position {Position} with size {Size}");
}
}
public record Ellipse(Position Position, Size Size) : Shape(Position, Size)
{
protected override void DisplayShape()
{
Console.WriteLine($"Ellipse at position {Position} with size {Size}");
}
}
Program.cs
Rectangle r1 = new(new Position(33, 22), new Size(200, 100));
Rectangle r2 = r1 with { Position = new Position(100, 22) };
Ellipse e1 = new(new Position(122, 200), new Size(40, 20));
DisplayShapes(r1, r2, e1);
void DisplayShapes(params Shape[] shapes)
{
foreach (var shape in shapes)
{
shape.Draw();
}
}
Project structure :
Question :
When I build the project and run the the project with the below command :
dotnet run --project .\RecordsInheritance\RecordsInheritance.csproj
I am getting output which i.e. DisplayShapes method is getting called and output is displayed.
The C# code in Program.cs is not wrapped inside a namespace and a class and yet it is getting executed correctly like a javascript code.
Can someone explain me how this code is getting executed correctly as the code is not wrapped inside a class and there is no public static method as well ?
This is a new feature in Visual Studio 2022 and .NET 6 SDK >
Top Level Statements
It is a simplified way to express the entry point of your applications.
In other words is a new way of writing the Program.cs class.
According to Microsoft
Top-level statements enable you to avoid the extra ceremony required
when writing your entry point.
Recent version of C# and .NET has few enhancements that you see:
file scoped namespces, that allow to write
namespace MyProject;
// All below does not need braces and indentation, it goes to above namespace
public class ......
due to that, template for console app could be simplified and now body of the file is just what would be places inside Main method, thus it gets executed and you don't need anthing execpt compiling code there
Further reading
File scoped namespaces
New Console App template
How do you create the transparency effects that you see in windows 10? Something like this:
I have no clue how to approach this in c#. Logically thinking I would take a snapshot of the desktop every time the form comes into focus. Then blur it and place it at 0, 0(screen to client coordinates). That doesn't seem very effective. Any help? Again. not an experienced C# programmer, so a detailed explanation would be much appreciated
Edit: I saw some the answers referring me to a page for alpha blending. This is not what I am looking for. I wanted to know how to create the blur that you see in the image, the rest I can figure out at my own pace
Though all of the comments and the answers say it is not possible for WinForms, it definitely works also for WinForms (as SetWindowCompositionAttribute can be called on a Win32 window handle):
internal enum AccentState
{
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_INVALID_STATE = 4
}
internal enum WindowCompositionAttribute
{
WCA_ACCENT_POLICY = 19
}
[StructLayout(LayoutKind.Sequential)]
internal struct AccentPolicy
{
public AccentState AccentState;
public int AccentFlags;
public int GradientColor;
public int AnimationId;
}
[StructLayout(LayoutKind.Sequential)]
internal struct WindowCompositionAttributeData
{
public WindowCompositionAttribute Attribute;
public IntPtr Data;
public int SizeOfData;
}
internal static class User32
{
[DllImport("user32.dll")]
internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
}
And then in your Form constructor:
public Form1()
{
InitializeComponent();
BackColor = Color.Black; // looks really bad with the default back color
var accent = new AccentPolicy { AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND };
var accentStructSize = Marshal.SizeOf(accent);
var accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
var data = new WindowCompositionAttributeData
{
Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY,
SizeOfData = accentStructSize,
Data = accentPtr
}
User32.SetWindowCompositionAttribute(Handle, ref data);
Marshal.FreeHGlobal(accentPtr);
}
Result:
Windows Forms doesn't support AcrylicBrush so far. Only UWP support this.
But you have a Win32 API SetWindowCompositionAttribute to simulate this behavior.
The SetWindowCompositionAttribute API
By calling the Windows internal API SetWindowCompositionAttribute, you can get a lightly blurred transparent Window but this transparency is much less than the AcyclicBrush.
How to implement it
Calling SetWindowCompositionAttribute API is not very easy, so I've written a wrapper class for easier usage. But it's for WPF only.
I've written two posts talking about this:
https://walterlv.github.io/post/win10/2017/10/02/wpf-transparent-blur-in-windows-10.html (not in English)
3 Ways to create a window with blurring background on Windows 10 - walterlv
Other options
It's recommended to use AcrylicBrush using UWP and you can read Microsoft's documents Acrylic material - UWP app developer | Microsoft Docs for more details about it.
You can get that by using some algorithms
I don't know will it work or not. When I see your post I just think and got this concept.
Get entire windows desktop wallpaper image by using copyscreen method
Draw that image into a new bitmap where bitmap width = screen resolution.width and bitmap height = screen resolution.height eg: Bitmap bm = new Bitmap (1920, 1080)
Learn how to blur a bitmap image in c#. There is many of blogs teaching how to blur a bitmap programmatically.
Make blur of captured desktop wallpaper image
Put a picture of inside the form and draw the blurred bitmap into picturebox
You can make FormBorderStyle.None to get rid of old borders
You should keep picturebox picture style = normal in order to get full blurred image
I have an application which uses a C++ DLL to communicate with a Canon Camera, methods in this C++ DLL are invoked from a C# application. What I've seen in the application is that when taking photos, the memory increases, of course. After I close the "Image Capture Window" the application still holds the same amount of memory as it did, when all of the images were captured.
Since my application exists of many layers of WPF UserControls, I thought that the "Image Preview UserControl" was unable to get garbage collected because of other controls subscribed to an event fired from this control. After some googling, I decided to implement the Weak Reference Pattern on the events.
//Source code found here: http://paulstovell.com/blog/weakevents
public sealed class WeakEventHandler<TEventArgs> where TEventArgs : EventArgs
{
private readonly WeakReference _targetReference;
private readonly MethodInfo _method;
public WeakEventHandler(EventHandler<TEventArgs> callback)
{
_method = callback.Method;
_targetReference = new WeakReference(callback.Target, true);
}
public void Handler(object sender, TEventArgs eventArgs)
{
var target = _targetReference.Target;
if (target != null)
{
var callback =
(Action<object, TEventArgs>)
Delegate.CreateDelegate(typeof (Action<object, TEventArgs>), target, _method, true);
if (callback != null)
{
callback(sender, eventArgs);
}
}
}
}
So, if I forget to unsubscribe some events the GC will collect them anyway. After some more testing, this approach did not work, so I decided to use the Redgate ANTS Memory Profiler
I took three snapshots:
Before taking images
After I took 4 images
After destruction of the wpf controllers
The result when comparing snapshot 1 and 3:
As you can see the amount of allocated Unmanaged Memory is the big problem here. My first thought would be that the C++ DLL isn't deallocating the allocated memory when the "Image Capture Window" is closed.
Am I correct that the problem is in the C++ plugin? Can I exclude the C# application? As far as I know, all code written in .NET is managed memory.
Based upon a comment here is how the image arrives from the C++ plugin to the C# plugin:
From the C++ plugin there is a callback like this:
_resultcallback(img->GetImageInfo().Data, img->GetImageInfo().Width, img->GetImageInfo().Height, img->GetImageInfo().BPP);
And the method which receives the image on the C# side:
private void OnResultImageCallback(IntPtr imagePtr, int width, int height, int bitsPerPixel)
{
_state = CameraState.InitializedStandby;
_cbResultData.Width = width;
_cbResultData.Height = height;
_cbResultData.BitsPerPixel = bitsPerPixel;
int memSize = bitsPerPixel * width * height / 8;
_cbResultData.data = new byte[memSize];
Marshal.Copy(imagePtr, _cbResultData.data, 0, memSize);
_deleteAllocatedImageFunction(imagePtr);
if (ImageCaptured != null)
ImageCaptured(_cbResultData.data, _cbResultData.Width, _cbResultData.Height, _cbResultData.BitsPerPixel);
_cbResultData.data = null;
}
I also have a method to clear the allocated memory in my C++ which takes in a byte-pointer like this:
BOOL CanonEDSDKWnd::ClearImageBuffer(BYTE* img) {
_debug->Write(_T("CanonEDSDKWnd::ClearImageBuffer"));
delete[] img;
return TRUE;
}
Which is called from the C# code with the IntPtr from the callback
_deleteAllocatedImageFunction(imagePtr);
I think your callback function should look like the following:
C++ side:
_resultcallback(
img // extend the signature
img->GetImageInfo().Data,
img->GetImageInfo().Width,
img->GetImageInfo().Height,
img->GetImageInfo().BPP
);
C# side:
private void OnResultImageCallback(IntPtr img, IntPtr imagePtr, int width, int height, int bitsPerPixel)
{
_state = CameraState.InitializedStandby;
_cbResultData.Width = width;
_cbResultData.Height = height;
_cbResultData.BitsPerPixel = bitsPerPixel;
int memSize = bitsPerPixel * width * height / 8;
_cbResultData.data = new byte[memSize];
Marshal.Copy(imagePtr, _cbResultData.data, 0, memSize);
_deleteAllocatedImageFunction(img);
if (ImageCaptured != null)
ImageCaptured(_cbResultData.data, _cbResultData.Width, _cbResultData.Height, _cbResultData.BitsPerPixel);
_cbResultData.data = null;
}
I'm using OpenTK to make a C# OpenGL application.
I'm trying not to use the GameWindow class to open a context - here is my class managing a window + context :
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Platform;
using OpenTK.Input;
class Window
{
private INativeWindow window_;
private IGraphicsContext context_;
private bool isExiting_;
public Window(int width, int height, bool fullscreen, string title = "StormEngine application")
{
window_ = new NativeWindow(width, height, title, fullscreen ? GameWindowFlags.Fullscreen : GameWindowFlags.FixedWindow, GraphicsMode.Default, DisplayDevice.Default);
context_ = new GraphicsContext(GraphicsMode.Default, window_.WindowInfo, 4, 4, GraphicsContextFlags.Default);
context_.MakeCurrent(window_.WindowInfo);
window_.Visible = true;
window_.KeyDown += (sender, e) =>
{
if (e.Keyboard[Key.Escape])
window_.Close();
};
isExiting_ = false;
}
public Window(int width, int height) : this(width, height, false) { }
public bool EndFrame()
{
context_.SwapBuffers();
window_.ProcessEvents();
return (window_.Exists && !isExiting_);
}
}
I'm then calling Window w = new Window(800, 480); to open a window.
But as soon as I make a call to an OpenGL method, in my case int programId = GL.CreateProgram();, I am given a AccessViolationException.
My guess is that OpenGL function pointers are not loaded correctly, but I cannot find where the problem happens (I get no information about what happens inside GL.CreateProgam()).
Any idea of what might be happening, why, and how to resolve that ? :)
Forget it, I found my mistake :)
In OpenTK, a GraphicsContext needs, once created and made current, to be loaded.
To do so, just after context_.MakeCurrent(window_.WindowInfo);, I added :
(context_ as IGraphicsContextInternal).LoadAll()
I had to figure it out from the GameWindow class source on Github, tho, because this way to create a window isn't documented at all ^^
And it now works like a charm. :)
How can I make floating windows use their design size (and not the Dock Panel Suite's default size) with the Weifenluo Dock Panel suite?
Hint: I tried a proposition from the Dock Panel Suite forums at SF.net, but that doesn't seem to work.
I stumbled across this question when looking for the answer myself, and found Timothy's answer to not work for me.
The problem was that the method he outlines also floated the window by default. (maybe that's a version difference)
I have solved this another way. I've created a base class that inherits from DockContent that all my document windows would inherit from. I then created another overload for the Show method that handles this (I used the DockPanelSuite source code to help build this method).
public void Show(DockPanel dockPanel, DockState dockState, Rectangle floatWindowBounds)
{
Show(dockPanel, dockState); //shows the panel like normal
//now for the part to initialize the float pane and size
if (DockHandler.FloatPane == null)
{
DockHandler.FloatPane = dockPanel.DockPaneFactory.CreateDockPane(this, DockState.Float, false);
DockHandler.FloatPane.FloatWindow.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
}
DockHandler.FloatPane.FloatWindow.Bounds = floatWindowBounds;
}
when CForm is derived from DockContent,
I have a method within my MDIContainerWindow which looks like this
public void ShowForm(CForm pForm)
{
pForm.MdiParent = this;
Size lS = pForm.Size;
dockPanel.DefaultFloatWindowSize = lS;
pForm.Show(dockPanel);
pForm.VisibleState = DockState.Float;
}
This is working for me (in VB):
Dim MyForm As New MyForm
MyForm.Show(DockPanel, New Rectangle(MyForm.Location, MyForm.Size))
MyForm.DockState = DockState.DockRight
This worked for me:
var topLeft = dockPanel1.Location;
topLeft.X += (dockPanel1.Size.Width / 2 - newForm.Size.Width / 2);
topLeft.Y += (dockPanel1.Size.Height / 2 - newForm.Size.Height / 2);
newForm.Show(dockPanel1, new Rectangle(topLeft, newForm.Size));