Setting the form icon for an XNA window? - c#

Is there any way of changing the icon for an XNA game form (i.e. the one that appears in the top left corner of the form, and on the taskbar)?
I currently have a multi-icon with a variety of sizes embedded, including a 16x16 one. Unfortunately the project property "Application -> Resources -> Icon and manifest" uses the 32x32 one and scales it down, rather than the native one.
I'd like to manually set the icon to use the 16x16 one contained in the icon I have, and if possible change it dynamically at run-time.
Thank you.

After reading this thread, I came up with the following code (from program.cs):
static void Main(string[] args)
{
using (Game1 game = new Game1())
{
((System.Windows.Forms.Form)System.Windows.Forms.Form.FromHandle(game.Window.Handle)).Icon = new System.Drawing.Icon("file.ico");
game.Run();
}
}
file.ico should be copied to the same place as your executable.
You have to reference these assemblies in your solution:
System.Windows.Forms
System.Drawing
You can also replace the Game.ico in your solution folder, which has same effect.

Related

Get Unity Editor-Only Variable (color of splash screen background) at Runtime

To create a dynamic fade-in effect from Unity's splash screen, I am trying to get the color of the splash screen background at runtime.
In the editor, the color can be found at Edit > Project Settings > Player > Splash Image > Background.
While researching on how to get this color, I stumbled upon
PlayerSettings.SplashScreen.backgroundColor. However, the PlayerSettings class is contained in the UnityEditor namespace, which cannot be accessed at runtime.
How could I dynamically during runtime get the color of the splash screen background?
Edit: Using an IL decompiler I discovered that the UnityEditor assembly solves this with an external method. However, I still don't see a way to fetch the background color out of the editor assembly.
public static Color backgroundColor
{
get
{
Color result;
PlayerSettings.SplashScreen.INTERNAL_get_backgroundColor(out result);
return result;
}
// ...
}
private static extern void INTERNAL_get_backgroundColor(out Color value);
Unity's built with the assumption that you'll never need this value at runtime so you'll need to pull some tricks to get around that. Something I've often done to solve this particular issue of making editor-only variables accessable is writing a pre-build step that saves any wanted data to a resource file that can then be read during runtime.
The only API's you'd need to do this are the IPreprocessBuild interface, Resources.Load, and the MenuItem attribute (MenuItem is optional but will make your workflow a bit easier).
First, implement an IPreprocessBuild (this one goes in an "Editor" directory and references UnityEditor) to save off the setting to a resource:
class BackgroundColorSaver : IPreprocessBuild
{
public int callbackOrder { get { return 0; } } // Set this accordingly
public void OnPreprocessBuild(BuildTarget target, string path)
{
SaveBkgColor();
}
[MenuItem("MyMenu/Save Background Splash Color")]
public static void SaveBkgColor()
{
// Save PlayerSettings.SplashScreen.backgroundColor to a
// file somewhere in your "Resources" directory
}
}
This class will have SaveBkgColor() called any time a build is kicked off and the MenuItem tag gives you the option to also call the function whenever you'd like (makes testing/iteration easier).
Afterwards, you'll want to write a runtime script that simply uses Resources.Load to load your asset and parse it/convert it into a Color object.
Those are the basics when it comes to making "editor-only" resources available during runtime. Some specifics for the most straight-forward way of doing this with a Color:
Save the Color variable as a TextAsset.
Use Color.ToString() when saving your Color and ColorUtility.TryParseHtmlString when loading it.
Also keep in mind that since you want this to be a blend from the splash screen, you're going to need to have this code run immediately (probably in an Awake() function on some behaviour in your first scene).
Side note: There are more efficient ways to save/load the Color as a binary blob instead of a raw text asset but this is straight-forward and that part can easily be swapped in and out while leaving the IPreprocessBuild implementation intact.

How to create a script icon in Unity3D?

I created a scipt and editor for it. Now I want to assosiate an icon with it like this:
How to do such thing? Cant find any documentation on this.
You can change the icon by selecting the Object in Project view. Then click the icon in the upper left corner in the Inspector. Then select Other.
[Picture Guide] So after you have selected the script, click on the icon marked in red in the picture below:
Look at the picture below for guidance.
If you want to assign an icon to a custom script, I believe you can create a gizmo icon for it and place the image at a project location that maps to the namespace of your script. My understanding is for each MonoBehaviour in your assembly, Unity looks for an associated icon with the name "<className> Icon" under the "Gizmos" folder, but the hierarchy must match the namespace.
So if your MonoBehavior is TestClass and its namespace is Company.Project.Foo, you would place the image in your project at "Assets/Gizmos/Company/Project/Foo/" and image name should be "TestClass Icon".
Your script will then have the icon associated with it when viewed in the Inspector, but I don't believe this will cause it to appear in the SceneView. You should use the DrawGizmo attribute on an editor script, if you want to make the icon appear in the SceneView or perform any other custom gizmo drawing.
In the following example screenshots, I have a script called SafeArea with the namespace Greyborn.Library. I placed the "SafeArea Icon.png" at "Assets/Gizmos/Greyborn/Library/", and the icon immediately appeared in the Inspector and Project windows.
I used a PNG. Other image types may be supported, however when I tested with a PSD image, the gizmo wouldn't show up. Be sure to set the Texture Type to "Editor GUI and Legacy GUI".

XNA with Windows Forms - Opening new window

Okay, so here we go. I'm attempting to make an application, using XNA as the base because of its renderer. One of the things that is necessary in this project is to open a new window (as a dialog), in which is embedded a separate XNA render panel. I'm using this as an interactive preview panel, so I absolutely need XNA to render in there. However, it seems XNA is not very well equipped to do this. I have tried various things myself, but to no avail (either producing errors and not rendering correctly, or rendering in the wrong aspect ratio, etc.). Normally, I would post code here, but since I have had such little luck, there isn't much to post.
My application currently consists of an XNA application embedded within a Form, and I have a button to open the preview panel, which in theory should pop up as a Form Dialog, containing the XNA renderer, to allow me to draw the preview. I have been trying this for several hours, and got nowhere, so I'm asking for a bit of help here.
Thanks, anyway.
EDIT: Okay, I've made a little progress, but I have 2 problems. Firstly, any textures drawn with a sprite batch appear the right dimensions, but filled with solid black. Also, when I open the dialog, and then close it, and close the application, I get an AccessViolationException. I strongly suspect the two errors are linked in some way.
Here is my code initialising the preview dialog. (a is a custom class that essentially consists of a LinkedList of Texture2D objects).
animPrev = new AnimationPreview(a);
animPrev.Show();
My AnimationPreview class is an extension of the Form class, and contains a PreviewControl object, which is an extension of the GraphicsDeviceControl found in the XNA Winforms sample. Note that my main form extends the XNA Game class, for various reasons.
The PreviewControl object is set up like this:
protected override void Initialize()
{
sb = new SpriteBatch(GraphicsDevice);
Application.Idle += delegate { Invalidate(); };
}
And the Draw method contains:
protected override void Draw()
{
GraphicsDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.Violet);
if (frame != null)
{
sb.Begin();
sb.Draw(Image, Vector2.Zero, Color.White);
sb.End();
}
}
This clears the background of the form violet, as expected, and draws a black box of the same size as Image. This is not expected. Hopefully someone can help me out here.
NOTE: An acceptable alternative would be to convert XNA Texture2D objects to System.Drawing.Image objects. However, I am using XNA 3.1, so I can't just save the texture to a stream and reload it.
Actually, after having tried this, it's a bit dodgy, and very slow, so I'd rather not do it this way.
Did you take a look at the following official tutorials / samples?
XNA WinForms Series 1: Graphics Device
XNA WinForms Series 2: Content Loading
They should explain everything in my opinion. You even find downloadable source for the samples.

Changing where the .exe window appears when debugging?

First of all I'm not sure if ".exe window" is the proper term. It's the window that pops up when you start the application.
I'm a game programmer, and when I'm debugging, I very rapidly start it up, look at the problem, then close it down again to make minor changes in the code, then start it again etc. I do this like once per minute, so it happens a lot. My problem is that the .exe window always appears at the middle of my main screen (where I'm coding), and I'm running double monitors, and I'd like the game window to appear on my second screen instead of my main screen (obscuring my code).
Can I change where the exe window appears in VS2010? I've looked around everywhere, it feels like. Or is it something that will have to be managed by a 3rd party program? If so, what program?
Edit:
OK, OK, I found the solution. I did a really dumb mistake where I didn't mention that I am using XNA, and not using winforms. Sorry for misleading you guys. Here's how I solved it:
First off I had to include:
using System.Runtime.InteropServices;
Then at the top of my main class I created a tiny class:
public static class User32
{
[DllImport("user32.dll")] public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
}
Then in my Initialize function I simply call:
#if DEBUG
User32.MoveWindow(Game.Window.Handle, 2000, 400, 600, 480, true);
#endif
It's a little ugly, but it's only for debugging and only called once, so psh.
Original solution found here: http://social.msdn.microsoft.com/forums/en-US/xnagamestudioexpress/thread/bc9588a9-542f-425b-9025-d69fe2b0b182/
You can set the Form.StartPosition property, or just manually write to the Left and Top properties of the form you want to move.
Option 1: You could set the appropriate properties on the window/form if a debugger is attached.
if (System.Diagnostics.Debugger.IsAttached)
{
// Set the window/form's top/left properties.
}
Option 2: Add a command line switch, use that as startup parameter (Properties->Debug->Commandline arguments), and then set the appropriate properties in the window/form:
private void Application_Startup(object sender, StartupEventArgs e)
{
if (e.Args.Any(arg => arg.Equals("/debugmode", StringComparison.OrdinalIgnoreCase))
// Set some value which you check in your main window.
}
Although you are not using winforms, you still change it in Xna by using winforms objects. I know you found a solution but here is how to change it without using interop.
Add a reference to System.Windows.Forms and System.Drawing to the References in the game project.
Resist the temptation to add using statements for these as it can cause ambiguity with some Xna objects (Point, for instance, which in Xna uses floats).
In the Game.Initialize method:
System.Drawing.Point p = new System.Drawing.Point(2000, 400);// or wherever you want
System.Windows.Forms.Control c = Control.FromHandle(this.Window.Handle);
c.Location = p;
the game window will now start at the screen 2000,400 location.
I would just call it the "main application window". Anyway, assuming you're using WinForms, this would put the window in the top left corner of the first screen that isn't your primary screen:
void Form1_Load(object sender, EventArgs e)
{
#if DEBUG
Location = Screen.AllScreens.First(s => !s.Primary).Bounds.Location;
#endif
}
If you've only got two monitors hooked up, it'll work fine. You could also get more creative and center the application window on the other monitor, maximize it, whatever. The #if could be substituted with if (System.Diagnostics.Debugger.IsAttached) as suggested by #Daniel if you wanted. I used the former just to present another alternative.

C#: Using .ico file with multiple images

I'm trying to set the images in a TreeView in C#, from a .ico file containing two icons: a 32x32 version and a 16x16 version. The images are setting, but .Net is choosing the 32x32 version, and scaling it down (which looks terrible) instead of choosing the readily available 16x16 image.
The relevant code:
ilTree.Images.Add(Properties.Resources.group);
ilTree.Images.Add(Properties.Resources.single);
ilTree.Images.Add(Properties.Resources.db);
treeStored.ImageList = ilTree;
Where am I going wrong?
Answer:
There are two things you must do to get this to work. The first, as mentioned below, is to manually specify the correct size to the image list. The second is that you will also probably have to specify the color depth. MSDN states that:
In the .NET Framework version 1.1 or later, the default is Depth8Bit.
...however, that did not prevent ImageList from removing colors from my 8-bit icon. Upon close inspection, my icons (there were three) were: 4bit, 4bit, 8bit. The two 4 bit icons shared palettes, however the 8bit had a different one. In total, there were 257 colors between the icons. Despite the only slight overflow, .Net knocked it down to a mere 20 colors.
You need to create a new Icon object. There is an overload for the constructor that accepts the original Icon object and a size. I don't know if the new Icon object will share the same HIcon, but it will draw properly. To be safe, I would recommend ensuring that both are disposed.
Set the ImageSize property of the ImageList to new Size(16, 16)

Categories

Resources