måndag 13 april 2009

Bortrest

Bortrest 3 veckor. Återkommer med mera devtips efter min resa!

onsdag 8 april 2009

DEVTIPS #16 Göra Syntax Highlight med RichTextBox utan flicker!



1) Skapa en klass som ärver av RichTextBox overrida WndProc för att äta en del paint messages (Hemligheten för att slippa flicker). I OnTextChanged eventet kan vi då styra när kontrollen skall ritas om genom att sätta m_bPaint.

    public class SyntaxRichTextBox : System.Windows.Forms.RichTextBox {

        private bool m_bDoEvents = true;
        private static bool m_bPaint = true;
        private string[] m_Keywords = new string[] { 
                                                     "require", "and", "break", "false", 
                                                     "in", "local", "nil", "not", "or", 
                                                     "return", "true", "do", "else", "elseif", 
                                                     "end", "for", "function", "if", "repeat", 
                                                     "then", "until", "while"
                                                   };


        protected override void WndProc(ref System.Windows.Forms.Message m) {
            // Tar bort flicker från RichTextBox
            if (m.Msg == 0x00f) {
                if (m_bPaint)
                    base.WndProc(ref m);
                else
                    m.Result = IntPtr.Zero;
            } else
                base.WndProc(ref m);
        }

        public SyntaxRichTextBox() {
        }

        protected override void OnKeyDown(KeyEventArgs e) {
            base.OnKeyDown(e);
        }

        protected override void OnTextChanged(EventArgs e) {
            if (m_bDoEvents == true) {
                m_bPaint = false;
                try {
                    int iCharIndex = GetFirstCharIndexOfCurrentLine();
                    int iLine = GetLineFromCharIndex(iCharIndex);
                    int iLength = Lines[iLine].Length;
                    SyntaxHighlight(iCharIndex, iLength);
                } catch {
                }
                m_bPaint = true;
            }
            base.OnTextChanged(e);
        }

        private void FindKeyWord(string sKeyword, Color oColor, int iCharIndex, int iLength) {
            int iIndex = Find(sKeyword, iCharIndex, (iCharIndex + iLength), RichTextBoxFinds.MatchCase | RichTextBoxFinds.WholeWord);
            while (iIndex >= 0) {
                SelectionColor = oColor;
                if ((iIndex + sKeyword.Length) < (iCharIndex + iLength)) {
                    iIndex = Find(sKeyword, iIndex + sKeyword.Length, (iCharIndex + iLength), RichTextBoxFinds.MatchCase | RichTextBoxFinds.WholeWord);
                } else {
                    break;
                }
            }
        }

        public void Initialize() {
            m_bDoEvents = false;
            for (int i = 0; i <>
                int chfi = GetFirstCharIndexFromLine(i);
                SyntaxHighlight(chfi, Lines[i].Length);
            }
            m_bDoEvents = true;
        }

        private void SyntaxHighlight(int iCharIndex, int iLength) {
            int index = iCharIndex;
            int length = iLength;
            int iCursorPos = SelectionStart;

            SelectionStart = iCharIndex;
            SelectionLength = iLength;
            SelectionColor = Color.Black;

            foreach (string sKeyword in m_Keywords) {
                FindKeyWord(sKeyword, Color.Blue, iCharIndex, iLength);
            }

            SelectionStart = index;
            SelectionLength = length;
            // find numbers
            Regex rNum = new Regex("[0-9]*");
            Match mNum = rNum.Match(SelectedText);
            while (mNum.Success) {
                if (mNum.Captures.Count > 0) {
                    string sExp = mNum.Captures[0].Value;
                    FindKeyWord(sExp, Color.DarkOrchid, iCharIndex, iLength);
                }
                mNum = mNum.NextMatch();
            }

            SelectionStart = index;
            SelectionLength = length;
            // find xml
            Regex rXml = new Regex("<[^>]*>");
            Match mXml = rXml.Match(SelectedText);
            while (mXml.Success) {
                if (mXml.Captures.Count > 0) {
                    string sExp = mXml.Captures[0].Value;
                    FindKeyWord(sExp, Color.MediumSlateBlue, iCharIndex, iLength);
                }
                mXml = mXml.NextMatch();
            }       

            // reset
            SelectionStart = iCursorPos;
            SelectionLength = 0;
            SelectionColor = Color.Black;
        }

    }

2) Användning:
         SyntaxRichTextBox srt = new SyntaxRichTextBox();
            this.Controls.Add(srt);
            srt.Dock = DockStyle.Fill;

tisdag 7 april 2009

DEVTIPS #15 Extensions: utöka befintliga klasser med egna metoder

I .NET 3.5 går det att använda Extensions för att utöka befintliga klasser med egna metoder.

Exempel:
string s = "42";
int num = s.ToNumber() * 8;

Så här skapar man en extension.
1) Skapa en statisk klass
2) En statisk metod med argumentet (this string)
Exempel:
   public static class QubeExtensions {
        public static int ToNumber(this string s) {
            try { return int.Parse(s); } catch { } return 0;
        }
    }

måndag 6 april 2009

DEVTIPS #14 Köra Stored Procedures enklare

För att få lite enklare hantering av ett datalager med en massa "Stored Procedures" kan man skapa en basklass som stänger connection i dispose.

   public class DbBase : IDisposable {
        protected SqlCommand mCommand = null;
        protected SqlConnection mConnection = null;
        protected SqlDataReader mReader = null;

        protected DbBase() {
            try {
                mConnection = new SqlConnection("connectionString goes here");
                mConnection.Open();
                mCommand = new SqlCommand();
                mCommand.Connection = mConnection;
                mCommand.CommandType = CommandType.StoredProcedure;
            } catch (Exception ex) {
                Dispose();
                throw ex;
            }
        }

        ~DbBase() {
            Dispose();
        }

        public void Dispose() {
            if (mConnection != null)
                mConnection.Close();
            if (mReader != null)
                mReader.Close();
        }
    }

Sedan skapar vi en klass som ärver av denna klass DbBase. Fördelen här är att vi inte behöver öppna och stänga connection hela tiden, det sköter basklassen DbBase om. Smidigt!

    public class DbDirectory : DbBase {
        public void pSerializedAdd(Guid EntryGUID, byte[] Data, string Name) {
            mCommand.CommandText = "Directory.pSerializedAdd";
            mCommand.Parameters.Clear();
            mCommand.Parameters.Add("@EntryGUID", SqlDbType.UniqueIdentifier).Value = EntryGUID;
            mCommand.Parameters.Add("@Data", SqlDbType.VarBinary).Value = Data;
            mCommand.Parameters.Add("@Name", SqlDbType.VarChar, 50).Value = Name;
            mCommand.ExecuteNonQuery();
        }

        public void pSerializedDelete(Guid EntryGUID, string Name) {
            mCommand.CommandText = "Directory.pSerializedDelete";
            mCommand.Parameters.Clear();
            mCommand.Parameters.Add("@EntryGUID", SqlDbType.UniqueIdentifier).Value = EntryGUID;
            mCommand.Parameters.Add("@Name", SqlDbType.VarChar, 50).Value = Name;
            mCommand.ExecuteNonQuery();
        }
    }

För att köra DbDirectory funktioner kör vi sedan med using som säkerställer att dispose i basklassen DbBase körs.
            using (DbDirectory dbDir = new DbDirectory()) {
                dbDir.pSerializedAdd(Guid.Empty, new byte[0], "test");
            }

fredag 3 april 2009

DEVTIPS #13 JavaScript 3D Text

Klistra in detta i en html fil och kör. Skapar ett textblock som roterar i 3D. Fredagsskoj...

<html>
<head>
    <title>Untitled Page</title>
    <script language="javascript" type="text/javascript">
        var aDivs = new Array();
        //Coordinates and letters
        var aPos = new Array();
        var angleX = 0, angleY = 0, angleZ = 0;
        var fl = 150, iv = 10;
        var str = "I AM BORED BEYOND BELIEF! I WANT SOME CAKE! IS THIS A STUPID TEXT OR WHAT? OK TIME FOR ME TO SIGN OFF..                         ";
        function onload() {
            var i, x, y;
            var index = 0;
            for (y = 50; y >= -50; y -= 10) {
                for (x = -50; x <= 50; x += 10) {
                    var ch = str.substr(index, 1);
                    aPos[index] = new Array();
                    aPos[index] = [x, y, 0, ch];
                    index++;
                }
            }

            for (i = 0; i <>
                createElement(aPos[i][3], aPos[i][0], aPos[i][1]);
            }
            setInterval(update, iv);
        }

        function update() {
            var i;
            var oDiv;
            var x, y, z
            var x1, y1, z1
            var xt1, yt1, zt1;
            var xc = 250, yc = 150;
            var add = 0;

            for (i = 0; i <>
                oDiv = aDivs[i];
                x = aPos[i][0]; y = aPos[i][1], z = aPos[i][2];
                x += Math.sin(angleX + add) * 50;
                y += Math.cos(angleY + add) * 20;
                add += 0.001;
                //Rotation about the z axis: 
                xt1 = (Math.cos(angleZ) * x) - (Math.sin(angleZ) * y);
                yt1 = (Math.sin(angleZ) * x) + (Math.cos(angleZ) * y);
                //Rotation about the y axis: 
                x1 = (Math.cos(angleY) * xt1) + (Math.sin(angleY) * z);
                zt1 = -(Math.sin(angleY) * xt1) + (Math.cos(angleY) * z);
                //Rotatation about the x axis: 
                y1 = (Math.cos(angleX) * yt1) - (Math.sin(angleX) * zt1);
                z1 = (Math.sin(angleX) * yt1) + (Math.cos(angleX) * zt1);
                //Color z-distance
                colorElement(oDiv, "#ffffff");
                if (z1 > -50) colorElement(oDiv, "#ddddff");
                if (z1 > -40) colorElement(oDiv, "#ccccff");
                if (z1 > -30) colorElement(oDiv, "#bbbbee");
                if (z1 > -20) colorElement(oDiv, "#aaaadd");
                if (z1 > -10) colorElement(oDiv, "#9999cc");
                if (z1 > 0) colorElement(oDiv, "#8888bb");
                if (z1 > 10) colorElement(oDiv, "#7777aa");
                if (z1 > 20) colorElement(oDiv, "#666688");
                if (z1 > 30) colorElement(oDiv, "#555577");
                if (z1 > 40) colorElement(oDiv, "#444466");
                if (z1 > 50) colorElement(oDiv, "#333355");
                //focal length
                scale = fl / (fl + z1);
                x1 = x1 * scale + xc;
                y1 = y1 * scale + yc;
                positionElement(oDiv, x1 * 1.5, y1 * 1.5);
            }
            angleX += 0.082; angleY += 0.14; angleZ += 0.05;
        }

        function colorElement(oDiv, color) {
            oDiv.style.color = color;
        }

        function createElement(str, x, y) {
            oDiv = document.createElement("DIV");
            oDiv.innerText = str;
            oDiv.style.position = "absolute";
            oDiv.style.pixelLeft = x;
            oDiv.style.pixelTop = y;
            document.body.insertBefore(oDiv);
            aDivs.push(oDiv);
            update();
        }

        function positionElement(oDiv, x, y) {
            oDiv.style.pixelLeft = x;
            oDiv.style.pixelTop = y;
        }
    </script>

</head>
<body onload="onload();" style="background-color: #222244; font-family: verdana;
    font-weight: bold;">
</body>
</html>

torsdag 2 april 2009

Bloggkartan.se

Jag har placerat min blogg i Morabloggkartan.se!

DEVTIPS #12 ASP.NET Plugins

Att skapa plugins för ASP.NET sidor:

1) Fixa till ett Interface:
    public interface IPlugin {
        string Name {get; set;}
        void RenderContent(Control parent);
    }

2) Skapa en plugin som bygger på Interfacet från steg 1)
    public class MyPlugin : IPlugin {
        private string _name = "MyPlugin";

        public string Name {
            get {
                return _name;
            }
            set {
                _name = value;
            }
        }

        public void RenderContent(Control parent) {
            Label label = new Label();
            label.Text = "MyPlugin";
            parent.Controls.Add(label);
        }
    }

3) Kör pluginen dynamiskt på hemsidan:
    protected void Page_Load(object sender, EventArgs e)
    {
        string typeName = "myplugin.MyPlugin, myplugin, Version=0.0.0.0";
        Type type = Type.GetType(typeName);
        object o = Activator.CreateInstance(type);
        IPlugin plugin = (IPlugin)o;
        plugin.RenderContent(pnlMain);
    }


DEVTIPS #11 ASP.NET Confirm

För att göra en liten extra check kan man lägga till eventet onclick via attributes.
javascripts confirm returnar true eller false, trycker man på avbryt så körs aldrig btnTest_Click eventet.

   protected void Page_Load(object sender, EventArgs e)
    {
        btnTest.Attributes.Add("onclick", "return confirm('Är du säker?');");
    }

    protected void btnTest_Click(object sender, EventArgs e) {
        // do your stuff here
    }

onsdag 1 april 2009

Träning

Det var så otroligt skönt att träna idag. 45 minuter löpband och 15 minuter styrketräning. Jag mår som en prins!!!

DEVTIPS #10 T-SQL Soundex() Function

Soundex är ett fonetiskt mönstermatchingssystem.
T ex lagras namnet "Nielsen" med N425 här nedan följer en förklaring.

Första bokstaven lagras och dom följande 3 fonetiska ljuden blir sparade enligt följande regler:
1 - B, F, P, V
2 - C, G, J, K, Q, S, X, Z
3 - D, T
4 - L
5 - M, N
6 - R

A,E,I,O,U,H,W,Y kastas bort.

"Nielsen" lagras som N425:
1. N Lagras
2. i och e kastas bort.
3. l ljudet sparas som 4.
4. s lagras som 2.
5. e kastas bort.
6. n lagras som 5. 

Soundex lagrar "Nielsen", "Nelson" och "Neilson" med samma kod: N425

SQL Exempel:
   SELECT LastName, FirstName
  FROM Customer
  WHERE SOUNDEX('Nielsen') = SOUNDEX(LastName)

Resultat:
  LastName FirstName
  ----------------------------------
  Nielsen  John
  Nelson  Robert
  Neilson  Anna

DEVTIPS #9 IsNull

Om en variabel är null och man vill snabbt sätta ett standardvärde
använd dubbla frågetecken ??:

   string message = null;
   MessageBox.Show(message ?? "NULL");

DEVTIPS #8 Javascript resources

Bästa stället för att lära sig avancerad javascript:
http://javascript.crockford.com/

Kolla in dessa videos av Douglas Crockford om du vill lära dig avancerad JavaScript

DEVTIPS #7 JSON Message

Class defenitions for serialization:
[Serializable]
public class JsonQuery
{
    public string licenseKey;
    public string layoutName;
    public List<JsonQueryItem> items;
}

[Serializable]
public class JsonQueryItem
{
    public string fieldRef;
    public string comparison;
    public string value;
}

Javascript JSON Message:
   var query = {
                licenseKey: "3c67897",
                layoutName: "hemma",
                items: [
                    {
                        fieldRef: "PRODUCT_CODE",
                        comparison: "Contains",
                        value: "hepa"
                    }
                ]
            };

DEVTIPS #6 JSON Serialization with .NET

.NET 3.5 Has JSON serialization built-in.
Include these references:

using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;

Make a serializable object defenition (class):
[Serializable]
public class JsonQuery
{
    public string licenseKey;
    public string layoutName;
    public List items;
}

Make two generic functions for serialize and deserialize JSON Message:
    private object JsonDeserialize(string json, Type type)
    {
        MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
        DataContractJsonSerializer dcjs = new DataContractJsonSerializer(type);
        object o = dcjs.ReadObject(ms);
        ms.Close();
        return o;
    }

    private string JsonSerialize(object obj, Type type, string callback)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(type);
        MemoryStream ms = new MemoryStream();
        ser.WriteObject(ms, obj);
        string json = Encoding.Default.GetString(ms.ToArray());
        ms.Close();
        return callback + "(" + json + ")";
    }