This post has been imported from the old blog and has not yet been converted to the new syntax yet.
I added another article in the 'Basic C# Examples'-series. ;)


It should answer the question of how to make nonsquare windows?

There is another example out there (which I can't find the link of anymore) that uses pointers to run over the image. Because of performance issues. So, I decided to take the GetPixel approach and see if it worked. And it does ;) Don't notice any performance hit here thou, maybe on weaker computers..

How To Make Non-Rectangular Forms.
 
This post has been imported from the old blog and has not yet been converted to the new syntax yet.
I received some good feedback from my previous article (A Console IRC Bot) and here is the next one.

The question for this article was how to make nonsquare windows?.

It's actually very easy according to the MSDN site. You add this piece of code to your form and voila, non-square.

[csharp]
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
System.Drawing.Drawing2D.GraphicsPath shape = new System.Drawing.Drawing2D.GraphicsPath();
shape.AddEllipse(0, 0, this.Width, this.Height);
this.Region = new System.Drawing.Region(shape);
}
[/csharp]

But that's too easy, right? Well, actually, the setting is easy, it's creating the Region that's difficult. You could go looking for tutorials on how to draw shapes, but it could take a long time before you create your Region with shapes.

So, what we'll do here, is create a class that will allow us to make an image in any graphics program, that will represent our visible area.

Let's start with drawing something we want to use as a form.



Create a WinForm app (NonSquareForm). And immediately add a class to it.

This is were we begin:

[csharp]
using System;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace System.Drawing.Drawing2D {
public class RegionConvert {

} /* RegionConvert */
} /* System.Drawing.Drawing2D */
[/csharp]

The first method we'll create is ConvertFromTransparentBitmap which will take a Bitmap and a Color. The Color indicates which area will be removed from the resulting Region.

To start, we begin with finding the dimensions of our image.

[csharp]
// First we get the dimensions of our image
GraphicsUnit aPixel = GraphicsUnit.Pixel;
RectangleF imageBoundsF = imageRegion.GetBounds(ref aPixel);
int imageWidth = Convert.ToInt32(imageBoundsF.Width);
int imageHeight = Convert.ToInt32(imageBoundsF.Height);
[/csharp]

As you can see from the above MSDN example, we need a GraphicsPath, where we will add all our non-transparent pixels to.

[csharp]
// This will be the path for our Region
GraphicsPath regionPath = new GraphicsPath();
[/csharp]

And for the logic of our method, we'll loop over the image pixel per pixel and determine if it's transparent or not.

[csharp]
// We loop over every line in our image, and every pixel per line
for (int intY = 0; intY < imageHeight; intY++) {
for (int intX = 0; intX < imageWidth; intX++) {
if (imageRegion.GetPixel(intX, intY) != transparentColor) {
// We have to see this pixel!
regionPath.AddRectangle(new Rectangle(intX, intY, 1, 1));
}
}
}
[/csharp]

When we have all our pixels in our path, we'll create a Region out of it, and return it.

[csharp]
Region formRegion = new Region(regionPath);
regionPath.Dispose();
return formRegion;
[/csharp]

Now we go to our Form, you'll have to set the FormBorderStyle property to None.

Add the following code to your Form constructor:

[csharp]
// Read the background file
FileStream imageStream = File.OpenRead("Glass.bmp");
Bitmap imageBackground = (Bitmap)Bitmap.FromStream(imageStream);
Color transparentColor = Color.FromArgb(0xFF, 0x00, 0xFF);

// Make our form fit the background
this.Width = imageBackground.Width;
this.Height = imageBackground.Height;

// Apply custom region with FF00FF as transparent color
this.Region = RegionConvert.ConvertFromTransparentBitmap(imageBackground, transparentColor);
this.BackgroundImage = imageBackground;
[/csharp]

Glass.bmp is a bitmap that lives next to your .exe file. Now you got a non-rectangular form!

Of course you will have to add your own methods of minimizing, closing and moving the form now.

I uploaded the project as an example. You can drag it around and press 'Q' to quit.

Stay tuned for more! ;)


Update: I wrote an article about how to include the bitmap in the .exe, check it out: Including Resources in .exe.
 
This post has been imported from the old blog and has not yet been converted to the new syntax yet.
I was thinking last night, all posts here are very great, and made by all those smart people. But why is it that my fellow students hardly read them? Or why don't you hear them a lot?

Some of my possible conclusions were:

  • It's too hard, most of the posts here require background or understanding, which we as students don't have that much yet.

  • No real basic examples. There are snippets, there is a lot of code being posted here, but the target audience here isn't the beginning programmer, we mostly write for people who already know a lot.

  • ...?



And because of that, and because I want to raise interest among the people I know, I decided to ask them for questions they had about C#, and try to answer them by example.

I'm gathering subjects to write on, very basic subjects, appealing to students as well. And I'll try to create an application that answers their question and provides code they could extend.

Hopefully I can keep this up, because I'm learning a lot from it as well. It helps you to think of subjects you wouldn't have thought of otherwise. And I have to check out docs and examples as well to write an article about it from scratch.

The first article is about 'How to get on IRC with C#'. I created a basic Console IRC Bot along with some comments. The example uses tcp connections, streams and events. Source code is provided as well.

I hope other students like the idea... (not only students by the way, everyone can use samples!)

Let me know if this is a good plan. (Or if you have negative comments, go ahead as well ;))
 
This post has been imported from the old blog and has not yet been converted to the new syntax yet.
I'm planning to write some articles based on questions I get from fellow students.

The first one is how to get on IRC with C#?. So, here it is, the first article of (hopefully) many.

Let's start by telling what IRC is. This is best done by reading the Internet Relay Chat Protocol RFC. You can find anything you want about the IRC protocol in there.

Getting on IRC is as simple as:

  • Establishing a connection.

  • Logging in.

  • Maintaining a connection and reacting to commands.


As this is an article on how to establish an IRC connection and work with the commands, I'm not going to spent any time on UI. Therefore this will be a simple Console Application (cIRC).

We'll make a seperate class for the IRC functions so we could re-use it later when we want to add a UI.

[csharp]
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace System.Net {
public class IRC {

} /* IRC */
} /* System.Net */
[/csharp]

Needed info.

Let's think about what info we need for a connection.

First of all, the server and port ofcourse. Then the nickname to be used, and also the userinfo. The userinfo contains the actual username (used in ident), and the Real Name (which you can see when doing a WHOIS).

So, add the IrcServer, IrcPort, IrcNick, IrcUser and IrcRealName properties.

For this example I'm going to create a single channel IRC bot. So we can also add an IrcChannel property. If you would take this further you would split that off. The first thing I'm thinking of is, create a channel object and manage each channel you're on with one of those.

I also added a bool IsInvisible property, as this is the only mode you can set as a normal user (See 3.1.5 User mode message).

The Connection.

Now that we have all our info to make our first connection, let's implement it.

I'll be using this application as an example on how to create events as well.

To start our bot, we will just have one event. The eventReceiving. This will occur every time a command gets received from the IRC server. For now we'll just write it to the console.

What we need is the following. After our namespace we add:

[csharp]
public delegate void CommandReceived(string IrcCommand);
[/csharp]

And right after our class we add:

[csharp]
public event CommandReceived eventReceiving;
[/csharp]

This is how our application will look as a start:

[csharp]
using System;
using System.Net;

namespace cIRC {
class cIRC {
static void Main(string[] args) {
IRC cIRC = new IRC("CumpsD", "#mypreciousss");
cIRC.eventReceiving += new CommandReceived(IrcCommandReceived);
cIRC.Connect("efnet.xs4all.nl", 6667);
} /* Main */

static void IrcCommandReceived(string IrcCommand) {
Console.WriteLine(IrcCommand);
} /* IrcCommandReceived */
} /* cIRC */
} /* cIRC */
[/csharp]

As you can see, we have bound the eventReceiving to a local method, which will handle the data.

I'll supply the source at the end of the article so you can check out the constructor and other details yourself.

The logic behind our bot is that after we launch the .Connect on it, it keeps running, and fires off events when it detects a command. For this article I'll display everything to the console in a nice format.

First, we connect with the server and register ourself.

[csharp]
// Connect with the IRC server.
this.IrcConnection = new TcpClient(this.IrcServer, this.IrcPort);
this.IrcStream = this.IrcConnection.GetStream();
this.IrcReader = new StreamReader(this.IrcStream);
this.IrcWriter = new StreamWriter(this.IrcStream);

// Authenticate our user
string isInvisible = this.IsInvisble ? "8" : "0";
this.IrcWriter.WriteLine(String.Format("USER {0} {1} * :{2}", this.IrcUser, isInvisible, this.IrcRealName));
this.IrcWriter.Flush();
this.IrcWriter.WriteLine(String.Format("NICK {0}", this.IrcNick));
this.IrcWriter.Flush();
this.IrcWriter.WriteLine(String.Format("JOIN {0}", this.IrcChannel));
this.IrcWriter.Flush();
[/csharp]

I don't have any error handling when you pick an already chosen nick. You can implement that in the listener loop and abort the connection, let the user choose another nick, and retry.

After we are connected there is a listening loop which looks like:

[csharp]
// Listen for commands
while (true) {
string ircCommand;
while ((ircCommand = this.IrcReader.ReadLine()) != null) {
if (eventReceiving != null) { this.eventReceiving(ircCommand); }

string[] commandParts = new string[ircCommand.Split(' ').Length];
commandParts = ircCommand.Split(' ');
if (commandParts[0].Substring(0, 1) == ":") {
commandParts[0] = commandParts[0].Remove(0, 1);
}

if (commandParts[0] == this.IrcServer) {
// Server message
switch (commandParts[1]) {
case "332": this.IrcTopic(commandParts); break;
case "333": this.IrcTopicOwner(commandParts); break;
case "353": this.IrcNamesList(commandParts); break;
case "366": /*this.IrcEndNamesList(commandParts);*/ break;
case "372": /*this.IrcMOTD(commandParts);*/ break;
case "376": /*this.IrcEndMOTD(commandParts);*/ break;
default: this.IrcServerMessage(commandParts); break;
}
} else if (commandParts[0] == "PING") {
// Server PING, send PONG back
this.IrcPing(commandParts);
} else {
// Normal message
string commandAction = commandParts[1];
switch (commandAction) {
case "JOIN": this.IrcJoin(commandParts); break;
case "PART": this.IrcPart(commandParts); break;
case "MODE": this.IrcMode(commandParts); break;
case "NICK": this.IrcNick(commandParts); break;
case "KICK": this.IrcKick(commandParts); break;
case "QUIT": this.IrcQuit(commandParts); break;
}
}
}

this.IrcWriter.Close();
this.IrcReader.Close();
this.IrcConnection.Close();
}
[/csharp]

What is happing here is:

First we fetch a command coming from the server.

Then we split it up into parts, delimited by a space and then we decide what action to take depending on wether it's a server command or a normal user mode command.

The server and user codes can be found in the RFC if you want to add more.

Responding to commands.

My plan was just to display data, but let me show you how you can respond to commands. I know this could be solved cleaner, but I'm writing this as a proof of concept and to explain what would be required and how it works.

We want to welcome everyone joining a channel. But we want it by notice. When someone joins the IrcJoin method gets called:

[csharp]
private void IrcJoin(string[] IrcCommand) {
string IrcChannel = IrcCommand[2];
string IrcUser = IrcCommand[0].Split('!')[0];
if (eventJoin != null) { this.eventJoin(IrcChannel.Remove(0, 1), IrcUser); }
} /* IrcJoin */
[/csharp]

Which in turns fires the join event and gets processed in our console app:

[csharp]
private void IrcJoin(string IrcChan, string IrcUser) {
Console.WriteLine(String.Format("{0} joins {1}", IrcUser, IrcChan));
IrcObject.IrcWriter.WriteLine(String.Format("NOTICE {0} :Hello {0}, welcome to {1}!", IrcUser, IrcChan));
IrcObject.IrcWriter.Flush ();
} /* IrcJoin */
[/csharp]

I modified our console app a bit so it would create an object of itself in the Main with our IrcObject as a private variable. That way I can access the IrcWriter I created in there. Ofcourse it is a bad idea to make that writer public. A better practice would be to create methods like NoticeUser, KickUser, etc... to control it's behaviour. But that exceeds the purpose of this article.

This concludes how you use C# to get on IRC.

Here are some ideas where you could extend this application:


  • Listen for certain triggers in the channel, then do some action. (Example: '!google searchterm', have your app do a query and reply the results)

  • Make this bot an opp and listen in PRIVMSG for a user to authenticate and op him. (Authenticate him against Active Directory, that way you'll learn how to work with AD as well)

  • Detect kicks against trusted users and take action to prevent takeovers, or auto rejoin when the bot gets kicked.

  • ...



Hopefully this answered the question, feel free to leave a comment when you have any questions.

I uploaded the source so you could learn from them. Enjoy!
 
This post has been imported from the old blog and has not yet been converted to the new syntax yet.
The Longhorn SDK enables you to create XAML apps from VS.NET, so I did.

One of the things I'll be looking for is an editor that generates XAML for me. Because, I find XAML "difficult" to write. Yes it's powerful and "easy" to do, but if you have to do it all by hand, it takes time. So I'm hoping there will be some editor fast :)

I've seen the demo during the DevDays, where you had a different layout per user. And one of those was the kiddie layout, with the very cool button, which was shaped totally different. So I set out course to create a 'NTFS Permissions For Dummies'.

Here's what i created in Photoshop as a quick idea of what I wanted:



Looks kiddie enough, doesn't it?

Then I started my quest, it seems Longhorn doesn't like it when i want to skew a Listbox with AngleX. When I go over the items it renders strange lines everywhere in my app. Gone was my idea to create these nice shaped controls.

But the gradient worked! And that's actually very nice.

Here's what I ended up with:

Update:
Here's an example of my skew experience: AngleX, AngleY. Notice the blue lines.
This is the XAML I used. It also happens with other values.