177 lines
No EOL
5.1 KiB
C#
177 lines
No EOL
5.1 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using MyClasses.MetaViewWrappers;
|
|
|
|
namespace MosswartMassacre.Views
|
|
{
|
|
public class BaseView : IDisposable
|
|
{
|
|
#region Windows API for boundary checking
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct RECT
|
|
{
|
|
public int Left;
|
|
public int Top;
|
|
public int Right;
|
|
public int Bottom;
|
|
|
|
public int Width { get { return Right - Left; } }
|
|
public int Height { get { return Bottom - Top; } }
|
|
}
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
|
|
#endregion
|
|
|
|
internal IView view;
|
|
protected PluginCore pluginCore;
|
|
|
|
public BaseView(PluginCore core)
|
|
{
|
|
pluginCore = core;
|
|
}
|
|
|
|
protected void CreateFromXMLResource(string resourcePath)
|
|
{
|
|
try
|
|
{
|
|
view = ViewSystemSelector.CreateViewResource(PluginCore.MyHost, resourcePath);
|
|
// Note: IView doesn't have VisibleChanged event, so we'll check bounds manually when needed
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PluginCore.WriteToChat($"Error creating view from {resourcePath}: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
protected void KeepWindowInBounds()
|
|
{
|
|
try
|
|
{
|
|
RECT rect = new RECT();
|
|
IntPtr gameWindowHandle = PluginCore.MyHost?.Decal?.Hwnd ?? IntPtr.Zero;
|
|
|
|
if (gameWindowHandle != IntPtr.Zero && GetWindowRect(gameWindowHandle, ref rect))
|
|
{
|
|
Point currentLocation = view.Location;
|
|
Size viewSize = view.Size;
|
|
|
|
// Check if window is outside right boundary
|
|
if (currentLocation.X + viewSize.Width > rect.Width)
|
|
{
|
|
currentLocation.X = rect.Width - viewSize.Width;
|
|
}
|
|
// Check if window is outside left boundary
|
|
else if (currentLocation.X < 0)
|
|
{
|
|
currentLocation.X = 20;
|
|
}
|
|
|
|
// Check if window is outside bottom boundary
|
|
if (currentLocation.Y + viewSize.Height > rect.Height)
|
|
{
|
|
currentLocation.Y = rect.Height - viewSize.Height;
|
|
}
|
|
// Check if window is outside top boundary
|
|
else if (currentLocation.Y < 0)
|
|
{
|
|
currentLocation.Y = 20;
|
|
}
|
|
|
|
// Only update location if it changed
|
|
if (currentLocation != view.Location)
|
|
{
|
|
view.Location = currentLocation;
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Don't spam chat with boundary check errors, just log silently
|
|
}
|
|
}
|
|
|
|
protected virtual void SaveWindowPosition()
|
|
{
|
|
// Override in derived classes to save position to settings
|
|
}
|
|
|
|
protected virtual void RestoreWindowPosition()
|
|
{
|
|
// Override in derived classes to restore position from settings
|
|
}
|
|
|
|
public virtual void Initialize()
|
|
{
|
|
try
|
|
{
|
|
RestoreWindowPosition();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PluginCore.WriteToChat($"Error initializing view: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public virtual void Show()
|
|
{
|
|
if (view != null)
|
|
{
|
|
view.Visible = true;
|
|
}
|
|
}
|
|
|
|
public virtual void Hide()
|
|
{
|
|
if (view != null)
|
|
{
|
|
view.Visible = false;
|
|
}
|
|
}
|
|
|
|
public virtual void Toggle()
|
|
{
|
|
if (view != null)
|
|
{
|
|
view.Visible = !view.Visible;
|
|
}
|
|
}
|
|
|
|
#region IDisposable Support
|
|
private bool disposedValue = false;
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (!disposedValue)
|
|
{
|
|
if (disposing)
|
|
{
|
|
try
|
|
{
|
|
SaveWindowPosition();
|
|
|
|
if (view != null)
|
|
{
|
|
view.Dispose();
|
|
}
|
|
view = null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
PluginCore.WriteToChat($"Error disposing view: {ex.Message}");
|
|
}
|
|
}
|
|
disposedValue = true;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
}
|
|
#endregion
|
|
}
|
|
} |