-
-
Notifications
You must be signed in to change notification settings - Fork 25
Description
I didn't think my first issue here would be something so silly and is probably the easiest thing in the world, but quite simply I'm wondering how you set the application icon for the window when building with OpenGL?
Right now I'm doing two builds: DX11 and OpenGL. For DX11, the icon I set in the csproj just works for both the application icon and the window icon. For OpenGL, it works for the application icon but the window icon it uses the KNI default icon. I've tried a bunch of different things but nothing seems to work. So my question is, how do you set the icon for the window?
Edit: I finally found a solution to this that works, but it seems a bit.. over the top?
It starts with a class importing SDL2 and setting icon via bitmap:
using System;
using System.IO;
using System.Runtime.InteropServices;
internal static class SdlWindowIcon
{
private const string SDL2_LIB = "SDL2";
[DllImport(SDL2_LIB, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SDL_RWFromMem(IntPtr mem, int size);
[DllImport(SDL2_LIB, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SDL_LoadBMP_RW(IntPtr src, int freesrc);
[DllImport(SDL2_LIB, CallingConvention = CallingConvention.Cdecl)]
private static extern void SDL_SetWindowIcon(IntPtr window, IntPtr icon);
[DllImport(SDL2_LIB, CallingConvention = CallingConvention.Cdecl)]
private static extern void SDL_FreeSurface(IntPtr surface);
public static bool TrySetIconFromBmpStream(IntPtr sdlWindowHandle, Stream bmpStream)
{
if (sdlWindowHandle == IntPtr.Zero || bmpStream == null)
return false;
using var ms = new MemoryStream();
bmpStream.CopyTo(ms);
var bytes = ms.ToArray();
if (bytes.Length == 0)
return false;
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
// Create an SDL RWops from our pinned buffer
IntPtr rw = SDL_RWFromMem(handle.AddrOfPinnedObject(), bytes.Length);
if (rw == IntPtr.Zero)
return false;
// Load a surface from the RWops. freesrc=1 => SDL will free RWops.
IntPtr surface = SDL_LoadBMP_RW(rw, 1);
if (surface == IntPtr.Zero)
return false;
try
{
SDL_SetWindowIcon(sdlWindowHandle, surface);
return true;
}
finally
{
SDL_FreeSurface(surface);
}
}
finally
{
handle.Free();
}
}
}Some stuff in Game1.cs:
private bool _windowIconSet;
private void TrySetWindowIconBmp()
{
if (_windowIconSet)
return;
if (Window?.Handle == IntPtr.Zero)
return;
try
{
using var stream = TitleContainer.OpenStream("icon.bmp");
if (SdlWindowIcon.TrySetIconFromBmpStream(Window.Handle, stream))
_windowIconSet = true;
}
catch { }
}And this in the main update loop:
protected override void Update(GameTime gameTime)
{
#if !WINDOWS
TrySetWindowIconBmp();
#endif
}There has to be a better solution to this, right? If not it is what it is, but if there's not there probably should be.