Applying To a form

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Ali Rizwan
    Banned
    Contributor
    • Aug 2007
    • 931

    Applying To a form

    Well
    I have made a form with I have made mine titlebar and borders.
    Now I want to make an ocx for it and want that it applies on form automatically.
    And one thing more.
    I write a code of moving and transparency once and then call them in all my forms with help of single line.
    I just call a function or make an ocx and it set form's border style to none and add a label on top of form and three shapes acting as borders of form. And automatically add the code used by these controls.

    Thanx

    >> ALI <<
    Last edited by Killer42; Dec 13 '07, 01:14 AM.
  • Dököll
    Recognized Expert Top Contributor
    • Nov 2006
    • 2379

    #2
    Originally posted by Ali Rizwan
    Well
    I have made a form with I have made mine titlebar and borders.
    Now I want to make an ocx for it and want that it applies on form automatically.
    And one thing more.
    I write a code of moving and transparency once and then call them in all my forms with help of single line.
    I just call a function or make an ocx and it set form's border style to none and add a label on top of form and three shapes acting as borders of form. And automatically add the code used by these controls.

    Thanx

    >> ALI <<
    That's a good one, Ali Rizwan!

    What are you trying to do with this ocx of yours?

    Why do you think you need an ocx file?

    Have a great week-end!

    Dököll

    Comment

    • Ali Rizwan
      Banned
      Contributor
      • Aug 2007
      • 931

      #3
      Originally posted by Dököll
      That's a good one, Ali Rizwan!

      What are you trying to do with this ocx of yours?

      Why do you think you need an ocx file?

      Have a great week-end!

      Dököll
      Have you checked my post cool form.
      I want to apply that style to all forms using an ocx.

      Thanx

      >> Ali <<

      Comment

      • Dököll
        Recognized Expert Top Contributor
        • Nov 2006
        • 2379

        #4
        Originally posted by Ali Rizwan
        Have you checked my post cool form.
        I want to apply that style to all forms using an ocx.

        Thanx

        >> Ali <<
        Here's a link I found for you, Ali:

        http://msdn2.microsoft .com/en-us/library/ms973283.aspx


        This is just an idea I thought you could probably use. I will add the information here in case link no longer works:

        Coding4fun
        Coding in the Blue Glow

        Duncan Mackenzie
        Microsoft Developer Network

        December 11, 2003

        Summary: Duncan Mackenzie describes how to control a serial-port–connected LCD panel using Microsoft Visual Basic .NET and Microsoft Visual C# .NET. (15 printed pages)

        Applies to:
        Microsoft® Visual Basic® .NET
        Microsoft® Visual C#®

        Download the source code for this article.



        I Just Love Blue Backlights
        I recently bought a new cell phone with a blue backlight, and I just love it; I press the keys just to get it to light up on my desk. Now I've found a way to bring that most excellent of features into my computer system—a backlit LCD Panel (see Figure 1).



        Figure 1. The bare panel, displaying its factory default startup text

        If you've read my past columns, you may already know about my home music system, but let me refresh your memory. I have this computer sitting in my living room, a silver cube that hooks up to the TV, displays my CD collection, and lets me play music through my stereo. Cool enough, but it only supports one form of display, the TV, which means that the TV has to be on to see what is playing or to control the system. (Well, actually you could control it without the TV on, as the remote works regardless, but the menus might be a bit tricky to navigate without any form of display.) Now, however, I have found a way to avoid turning the TV on for some of the simpler UI functions—by adding a cool blue backlit LCD panel (with arrow keys!) into my system. The panel, as shown uninstalled in Figure 2, hooks up to the serial port and can be communicated with using a full set of control codes.



        Figure 2. The panel mounted in a drive bay kit and hooked up, but not installed into my system

        Note I'm using a panel from Crystalfontz, model 633, but the same concepts should apply to other Crystalfontz panels (which share a similar command set in many cases) or to panels from other manufacturers.
        The first issue is figuring out how to talk to the device from within my Microsoft .NET Framework applications, how to send and receive information through the serial port. Serial communication is one of those unavoidable gaps in the .NET Framework. They couldn't cover everything, and it is just my luck that this is one of the areas that was left out. Luckily for me, there are components available to make this relatively painless.

        In this article I am going to show you three different approaches to communicating through the Serial Port: using the MSCOMM OCX that shipped with Microsoft® Visual Basic® 6.0, using the DBComm library that is available as a sample on GotDotNet, and using the library created by Sax, available as part of the Visual Basic .NET Resource Kit. The actual codes sent back and forth will be the same, as the communication method does not affect how the panel works, but I will abstract the panel control from the serial communication to allow me to switch between my three implementations as necessary. Before I get into the three "easy" implementations though, I'm going to discuss the underlying Win32 API calls for a few moments.

        Using the Win32 API
        Historically, using the Win32 API, it has been possible to work with a serial port or a parallel port as if it were a file. Once you opened a connection to these special files, you would use standard read and write functions to communicate to any connected hardware. Although the .NET Framework provides its own functions for working with files, they explicitly block you from opening a file stream using one of the special names such as "COM1." To get around this limitation, as well-intentioned as it might be, you could choose to use the Win32 API for all of your communication with the serial port—but there is another option that ends up being a lot easier for you.

        One of the constructor overloads for creating a file stream object in the .NET Framework takes a file handle as a parameter. This overload allows you to take the handle of a file opened through a Win32 API call (CreateFile in this case) and then create a .NET stream object against that file. When combined with some additional API calls (to set up the COM port for parity, stop bits, and so on) it is possible to do pretty much all of your serial port work using relatively "pure" .NET Framework code. There are several good samples of this technique available, including one from MSDN Magazine and quite a few on GotDotNet including the DBComm workspace.

        If you decide to handle all of the communication yourself, using the API, then you will certainly have a lot of control, although I would certainly recommend using an existing library whenever possible.

        Structuring the Application
        I am going to create a class (LCDPanel) that exposes the features of the LCD panel to the rest of my application(s), and that class will need to call into another class to handle the serial communication. I want to ensure that switching from one form of communication code (from the MSComm control to the Sax control, for example) is as easy as possible, so I decided to structure the application such that all communication between the panel-specific code and the serial-port code will have to go through the same Interface (ISerial). Each of my three serial communication classes will implement ISerial, and my panel code won't need to change at all when I change communication methods. A simple class, SerialFactory (shown below), will create the appropriate class instance (MSCOMMWrapper, SaxWrapper or DBCOMMWrapper) based on a string parameter.


        Copy Code
        Public Class SerialFactory
        Public Shared Function _
        GetSerialCommun ication( _
        ByVal libraryName As String) _
        As ISerial
        Dim result As ISerial
        Select Case libraryName.ToL ower
        Case "mscomm"
        result = New _
        MSCOMMWrapper.M SCOMMConnection
        Case "sax"
        result = New _
        SaxWrapper.SaxC OMM
        Case "dbcomm"
        result = New _
        DBCOMMWrapper.D BCommConnection
        Case Else
        Throw New ArgumentExcepti on( _
        "Library Not Found")
        End Select
        Return result
        End Function
        End Class
        ISerial, which exposes a simple set of methods and can even raise an event, is the only connection between the panel-specific code in LCDPanel and the serial communication classes:

        Copy Code
        Public Interface ISerial
        Sub Open(ByVal portName As String, _
        ByVal baudRate As Integer, _
        ByVal dataBits As Byte, _
        ByVal parity As parityOptions, _
        ByVal stopBits As stopBitOptions)

        Sub Open(ByVal port As Integer, _
        ByVal baudRate As Integer, _
        ByVal dataBits As Byte, _
        ByVal parity As parityOptions, _
        ByVal stopBits As stopBitOptions)

        Sub SendMessage( _
        ByVal message As Byte())

        Event DataAvailable( _
        ByVal sender As Object, _
        ByVal e As EventArgs)

        Sub Close()

        Function ReadMessage( _
        ByVal byteCount As Integer) As Byte()
        End Interface
        Note parityOptions and stopBitOptions are enums defined alongside ISerial to provide an easy way to specify these serial-port communication settings.
        Building the Communication Wrappers
        I then created a class for each of the three different communication methods, starting with the library from Sax. I will dig briefly into each of the three classes before showing you the LCDPanel class that handles the actual panel features.

        Using the Serial Communications Control from SAX
        Using this .NET library was the simplest and easiest of the three options. It was easy to configure and opening the port was intuitive.

        Copy Code
        'Assume "Imports Sax.Communicati ons"
        Public Overloads Sub Open(ByVal portName As String, _
        ByVal baudRate As Integer, _
        ByVal dataBits As Byte, _
        ByVal parity As parityOptions, _
        ByVal stopBits As stopBitOptions) _
        Implements ISerial.Open

        m_Sax = New SerialConnectio n

        Dim saxParity As Parity

        Select Case parity
        Case parityOptions.E venParity
        saxParity = Parity.Even
        Case parityOptions.M arkParity
        saxParity = Parity.Mark
        Case parityOptions.N oParity
        saxParity = Parity.None
        Case parityOptions.O ddParity
        saxParity = Parity.Odd
        Case parityOptions.S paceParity
        saxParity = Parity.Space
        End Select

        Dim saxStopBits As CommStopBits
        Select Case stopBits
        Case stopBitOptions. oneStopBit
        saxStopBits = CommStopBits.On e
        Case stopBitOptions. oneptfiveStopBi t
        saxStopBits = CommStopBits.On ePointFive
        Case stopBitOptions. twoStopBit
        saxStopBits = CommStopBits.Tw o
        End Select

        Dim options As New SerialOptions( _
        portName, baudRate, _
        saxParity, dataBits, _
        saxStopBits, False, _
        False, False, _
        False, False, False)

        Me.m_Sax.Option s = options
        Me.m_Sax.Open()
        End Sub
        The majority of that code is converting between a set of enums that I defined for the arguments in ISerial and whatever data types are required by the Sax control. I have to repeat this same type of code for the other two communication methods, to convert my generic values into the specific data types required. I defined the communication library (m_Sax in the code above) using the WithEvents keyword, which allows me to trap and handle the DataAvailable event.

        Copy Code
        Private WithEvents m_Sax As _
        Sax.Communicati ons.SerialConne ction

        Private Sub m_Sax_DataAvail able( _
        ByVal sender As Object, _
        ByVal e As System.EventArg s) _
        Handles m_Sax.DataAvail able
        RaiseEvent DataAvailable(M e, New EventArgs)
        End Sub
        In this case, I don't do any processing; I just raise another event (which is defined in ISerial) and let the calling class deal with pulling back the actual data by calling ISerial.ReadMes sage.

        Copy Code
        Public Function ReadMessage( _
        ByVal byteCount As Integer) _
        As Byte() Implements ISerial.ReadMes sage
        Dim finalBuffer(byt eCount) As Byte
        Dim loopCount As Integer
        Dim currentIndex As Integer = 0

        Do While m_Sax.Available > 0 _
        And currentIndex < byteCount
        If m_Sax.Available > 0 Then
        currentIndex += m_Sax.Read( _
        finalBuffer, currentIndex, _
        byteCount - currentIndex)
        End If
        Threading.Threa d.CurrentThread .Sleep(10)
        Loop
        ReDim Preserve finalBuffer(cur rentIndex - 1)
        Return finalBuffer
        End Function
        Connecting with the MSCOMM.OCX
        The first step in creating this library was adding a reference to the "Microsoft Communications Control 6.0" COM library. I have Visual Basic 6.0 installed on my development machines, so I had this control already available, but you might not be able to find it in the list of available COM references. If you own a copy of Visual Basic 6.0, you can install it and it will register this component on your system. If you don't have Visual Basic 6.0, you can simply remove the MSCOMMWrapper project from your solution and comment out any lines of code referencing it.

        As an "old-school" library, the MSCOMM library has a few quirks that made it hard to work with, such as a property (Input) that could return either an array of bytes or a string, depending on other settings. In the end, though, it works fine once you figure out all the properties and methods. I won't go through all of the code for this class (or for the DBCOMM wrapper, since the two of them are quite similar), but here is the MSCOMMWrapper's implementation of the Open and SendMessage methods.

        Copy Code
        Public Overloads Sub Open( _
        ByVal port As Integer, _
        ByVal baudRate As Integer, _
        ByVal dataBits As Byte, _
        ByVal parity As parityOptions, _
        ByVal stopBits As stopBitOptions) _
        Implements ISerial.Open

        m_MSCOMM.CommPo rt = port
        Dim settings As String

        Dim parityChar As Char
        Select Case parity
        Case parityOptions.E venParity
        parityChar = "E"c
        Case parityOptions.M arkParity
        parityChar = "M"c
        Case parityOptions.N oParity
        parityChar = "N"c
        Case parityOptions.O ddParity
        parityChar = "O"c
        Case parityOptions.S paceParity
        parityChar = "S"c
        End Select
        Dim stopBitsNumber As String
        Select Case stopBits
        Case stopBitOptions. oneptfiveStopBi t
        stopBitsNumber = "1.5"
        Case stopBitOptions. oneStopBit
        stopBitsNumber = "1"
        Case stopBitOptions. twoStopBit
        stopBitsNumber = "2"
        End Select
        'the MSCOMM Library expects its settings as
        'a string such as "9600,N,8,1 "
        settings = String.Format(" {0},{1},{2},{3} ", _
        baudRate, parityChar, _
        dataBits, stopBitsNumber)

        m_MSCOMM.Settin gs = settings
        m_MSCOMM.InputL en = 5
        m_MSCOMM.InBuff erSize = 5
        m_MSCOMM.InputM ode = _
        MSCommLib.Input ModeConstants.c omInputModeBina ry
        m_MSCOMM.RThres hold = 5

        m_MSCOMM.PortOp en = True
        End Sub


        Public Sub SendMessage( _
        ByVal message() As Byte) _
        Implements ISerial.SendMes sage
        m_MSCOMM.Output = message
        End Sub

        The MSCOMM library takes its settings in the form of a string (such as "9600,N,8,1 "), which is detailed in the MSDN documentation for the Settings property.

        Using the DBCOMM Library
        I opened up an empty Class file and started working on the ISerial implementation that used the DBCOMM library, when I realized how much faster it would be to just copy the MSCOMM wrapper I had already created and make a few changes. This worked out to be easier because the DBCOMM library was carefully designed to match the properties, methods, and behavior of the original MSCOMM control that shipped with Visual Basic 6.0. There are a few differences, but they are really just minor naming changes, so it doesn't take long to modify existing MSCOMM-based code to work against the DBCOMM library. Since the code for this wrapper is so similar to the MSCOMMWrapper, I won't go into it here in the article.

        Building the LCD Panel Code
        Once the underlying serial classes were created, along with the ISerial interface, I could move onto programming against the actual LCD panel itself. Communicating with most serial devices consists of reading and writing messages that conform to a very specific format. In the case of the CrystalFontz panel, that format is described in detail in a PDF available from the manufacturer's Web site.

        Sending Messages
        All messages sent to this panel have to follow the same format:

        The first byte contains a combination of two values, the type of message and the command number.
        The second byte contains the length of additional data (the number of additional bytes) that is attached to this command.
        The data for the command, if any is needed, is next.
        The last two bytes are a 16-bit checksum for the rest of the message.
        There isn't anything difficult about assembling this message, except for the checksum. The documentation for the panel specifies that the checksum is produced using the standard 16-bit CRC algorithm, often called crc16. Fortunately, I was able to find the details of this algorithm on the Web very quickly, but unfortunately, I found many different variations, all of which produced slightly different results. Without any real idea which one of the many code snippets corresponded to the formula expected by the panel, and suspecting that some of the code samples contained mistakes, I decided to check out CrystalFontz's own technical forums for an answer. Within a few moments, I located a perfect working sample written in Java. I copied that code down into a new C# class, made a few changes and compiled the result as a nice little CRC16 assembly (included with source in the download for this article).

        With the CRC problem solved, I created a function in my LCDPanel class that would take the command type, number, and any associated data as arguments and produce a properly formatted message to send to the panel.

        Copy Code
        Private Function FormatCommand( _
        ByVal type As CommandType, _
        ByVal commandCode As Command, _
        ByVal data As Byte()) As Byte()

        Dim results As Byte()
        Dim dataLength As Byte
        If data Is Nothing Then
        dataLength = 0
        Else
        dataLength = data.Length
        End If
        Dim totalLength As Integer = 4 + dataLength
        ReDim results(totalLe ngth - 1)

        Dim arrayToChecksum (totalLength - 3) As Byte
        arrayToChecksum (0) = (type << 6) Or commandCode
        arrayToChecksum (1) = dataLength
        If dataLength > 0 Then
        Array.Copy(data , 0, _
        arrayToChecksum , 2, dataLength)
        End If

        Dim checksum As Long
        checksum = Convert.ToInt64 ( _
        CRCUtilities.CR C16.compute(arr ayToChecksum))
        Dim checkBytes As Byte() = _
        BitConverter.Ge tBytes(checksum )

        Array.Copy(arra yToChecksum, _
        results, dataLength + 2)
        results(totalLe ngth - 2) = checkBytes(0)
        results(totalLe ngth - 1) = checkBytes(1)
        Return results
        End Function

        Writing a routine for each panel command was pretty easy now that all of the hard work was encapsulated into the message formatting and serial communication code. I only implemented a few of the 30 different commands supported by the panel, but I will probably add additional commands as the need arises.

        Copy Code
        Public Sub SetLine1(ByVal text As String)
        If text.Length > 16 Then
        text = text.Substring( 0, 16)
        Else
        text = text.PadRight(1 6)
        End If
        Dim command As Byte()
        Dim data As Byte()
        data = System.Text.ASC IIEncoding.ASCI I.GetBytes(text )
        command = _
        FormatCommand( _
        CommandType.nor mal, _
        LCDPanel.Comman d.SetLCDLine1, _
        data)
        Me.serial.SendM essage(command)
        End Sub

        Public Sub SetLine2(ByVal text As String)
        If text.Length > 16 Then
        text = text.Substring( 0, 16)
        Else
        text = text.PadRight(1 6)
        End If
        Dim command As Byte()
        Dim data As Byte()
        data = System.Text.ASC IIEncoding.ASCI I.GetBytes(text )
        command = _
        FormatCommand( _
        CommandType.nor mal, _
        LCDPanel.Comman d.SetLCDLine2, _
        data)
        Me.serial.SendM essage(command)
        End Sub

        Public Sub SetBacklight(By Val value As Byte)
        If value >= 0 And value <= 100 Then
        Dim command As Byte()
        Dim data(0) As Byte
        data(0) = value
        command = FormatCommand( _
        CommandType.nor mal, _
        LCDPanel.Comman d.SetLCDandKeyp adBacklight, _
        data)
        Me.serial.SendM essage(command)
        Else
        Throw New ArgumentExcepti on( _
        "Value must be within 0-100 range")
        End If
        End Sub

        Public Sub SetContrast(ByV al value As Byte)
        If value >= 0 And value <= 50 Then
        Dim command As Byte()
        Dim data(0) As Byte
        data(0) = value
        command = FormatCommand( _
        CommandType.nor mal, _
        LCDPanel.Comman d.SetLCDContras t, _
        data)
        Me.serial.SendM essage(command)
        Else
        Throw New ArgumentExcepti on( _
        "Value must be within 0-50 range")
        End If
        End Sub

        Public Sub StoreCurrentSta teAsBootState()
        Dim command As Byte()
        command = FormatCommand( _
        CommandType.nor mal, _
        LCDPanel.Comman d.StoreCurrentA sBoot, _
        Nothing)
        Me.serial.SendM essage(command)
        End Sub

        Public Sub ClearLCDScreen( )
        Dim command As Byte()
        command = FormatCommand( _
        CommandType.nor mal, _
        LCDPanel.Comman d.ClearScreen, _
        Nothing)
        Me.serial.SendM essage(command)
        End Sub

        Receiving Messages
        For the keypad buttons, I watched the data coming back from the serial port for a specific code (&H80) that indicated a key press or release. The data portion of the message (messages back from the panel follow the same format as the messages that you use to control it) indicated which particular key event had occurred.

        Copy Code
        Private Sub serial_DataAvai lable( _
        ByVal sender As Object, _
        ByVal e As System.EventArg s) _
        Handles serial.DataAvai lable
        Dim buffer() As Byte = Me.serial.ReadM essage(5)
        If Not (buffer Is Nothing OrElse buffer.Length < 3) Then
        If buffer(0) = &H80; Then 'keypress
        Dim loopCount As Integer
        Dim keyPressed As Byte = buffer(2)
        Dim bpArgs As New ButtonPushedEve ntArgs
        bpArgs.RawKeyCo de = CType(keyPresse d, KeypadCodes)
        Dim keyCode As Keys
        Dim keyAction As TypeOfKeypress

        Select Case bpArgs.RawKeyCo de
        Case KeypadCodes.KEY _DOWN_PRESS, _
        KeypadCodes.KEY _DOWN_RELEASE
        keyCode = Keys.DownKey
        If bpArgs.RawKeyCo de = _
        KeypadCodes.KEY _DOWN_PRESS Then
        keyAction = TypeOfKeypress. Press
        Else
        keyAction = TypeOfKeypress. Release
        End If
        'Repeat case block for each key
        '(up, down, left, right, enter and exit)
        End Select

        bpArgs.Key = keyCode
        bpArgs.TypeOfPr ess = keyAction

        RaiseEvent ButtonPushed(Me , bpArgs)
        End If
        End If
        End Sub


        [/CODE]
        [QUOTE]

        In the end, an application using the LCDPanel class, such as the test application (see Figure 3) included in the source code download, should not care what serial communication method is being used behind the scenes.



        Figure 3. The test application allows you to try out a selection of commands against the panel.

        As long as you implement the same interface and can produce the same results for each of the interface's methods, then the specific methods used should not affect the functionality of the application in any way. That has certainly been my experience, but I'm working against a single device and only using a small set of that device's features, so your results may vary.

        Resources
        The core of this article amounted to using three different serial communication libraries. The Microsoft COMM Control ships with Visual Basic 6.0, but more information on the other libraries is available on the web:

        Check out Sax on the Web at http://www.sax.net/, they have more than just serial communication components, so you might want to browse around.
        The DBComm workspace (created by Cory Smith) is available on GotDotNet at http://workspaces.gotdotnet.com/dbcomm, and you can also track Cory down at his personal site http://www.addressof.com.
        Other than these two libraries, I would suggest you read the following article:

        Use P/Invoke to Develop a .NET Base Class Library for Serial Device Communications (MSDN Magazine).
        Coding Challenge
        At the end of some of my Coding4Fun columns, I will have a little coding challenge—somet hing for you to work on if you are interested. For this article, the challenge is to create a .NET application that uses the serial or parallel port. Anything goes, whether you are trying to do your own modem work (although war dialing is frowned upon!), talk to a serial device like I am using, or even handle your own printing. Just post whatever you produce to GotDotNet and send me an e-mail message (at duncanma@micros oft.com) with an explanation of what you have done and why you feel it is interesting. You can send me your ideas whenever you like, but please just send me links to code samples, not the samples themselves (my inbox thanks you in advance).

        Have your own ideas for hobbyist content? Let me know at duncanma@micros oft.com, and happy coding!

        Comment

        • Ali Rizwan
          Banned
          Contributor
          • Aug 2007
          • 931

          #5
          Thanks a lot Dököll,
          You have searched for me and write this too much.
          I am very thankful to you.

          Thanks.
          >> ALI <<
          Last edited by Killer42; Dec 16 '07, 09:22 AM.

          Comment

          Working...