ads

Saturday, December 16, 2006

Using OwnerDraw For Good-Looking Controls

One of the easiest ways to speed up your graphics is to use the native API calls rather than the built in graphical methods. For example, using the API functions GetPixel and SetPixel is about 3x faster than using the built in methods PSet and Point. But while the the API is fast, you can get even better performance with direct memory access (DMA).

But wait! What about DirectX? Well, DirectX is great and is extremely fast for complex operations but most of its speed comes from its ability to interact with the coprocessor in your graphics card. If you don't have such a card (unlikely, true, but there it is) or if you are doing simple graphics (line and point stuff), then DMA is just as fast. Plus you don't need to distribute any particular version of DX.

Besides, I just like DMA. DX hides a lot of the logic of graphics which is great, but sometimes you can learn quite a bit from the algorithms behind a line, or a floodfill.

Anyway, here is how you do DMA.

The basic idea is that you access the actual bitmap that makes up the picture. You can do this indirectly by using the API functions GetDIBits and SetDIBits which extract a bitmap into an array and copy an array to a bitmap respectively, but you can do it directly if you had an array that pointed to the actual memory used by the bitmap.

To make such an array requires some API calls of course. Here they are:

Code:
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" _
(Ptr() As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" _
(ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long

Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type

Private Type SAFEARRAY2D
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
Bounds(0 To 1) As SAFEARRAYBOUND
End Type

Private Type BITMAP
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
The VarPtr function can get the actual memory address of a variable. In this case, we type the function in such a way that it works on arrays and we call it VarPtrArray. The CopyMemory function can copy data from one memory location to another. The GetObjectAPI function can retrieve information out of an object. In this case, we will use it to extract the BITMAP information from a stdPicture object, thus we need to define a BITMAP structure. Finally, we define a SAFEARRAY structure since this is the raw format behind an array and we need to mess with this to get this method to work.

So we start with a stdPicture object. We will assume that this object has a picture loaded. We also have a dynamic array of bytes, but this array has not yet had any memory assigned to it. We then use our API functions to assign the memory used by the picture object to the array, thus any changes we make to the array will show up in the picture.

Here is how we do it:

Code:
Dim SA As SAFEARRAY2D
Dim BMP As BITMAP
Dim mvarBytesPerPixel

Public Sub LoadPicArray(p As StdPicture,Data() As Byte)
If GetObjectAPI(p.Handle, Len(BMP), BMP) Then 'retrieve bitmap information about p
mvarBytesPerPixel = BMP.bmWidthBytes \ BMP.bmWidth
' make the local matrix point to bitmap pixels
With SA
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = BMP.bmHeight
.Bounds(1).lLbound = 0
.Bounds(1).cElements = BMP.bmWidthBytes
.pvData = BMP.bmBits
End With
' copy bitmap data into byte array
CopyMemory ByVal VarPtrArray(Data), VarPtr(SA), 4
End If
End Sub
So what happened? Well, first, we use the GetObjectAPI function to extract the BITMAP info. We then use this information to set up the SA SafeArray2D structure. In particular, notice the line:
.pvData = BMP.bmBits
which assigns the memory stored in the bitmap to the SA structure.

Now we simply make the Data array point to the SA structure with the CopyMemory function while using the VarPtr functions to get the actual memory addresses of the SA structure and the array.

Simple? Well, not exactly....there are some caveats...
1) The Picture object MUST have a picture preloaded. This will set up the objects BMP structure. Otherwise, it will be uninstantiated.
2) The SA object MUST persist for the life of the array. Remember, the array points to the SA structure so if you destroy SA before you terminate the array, the array will point to nothing.
3) Before you destroy the array, you MUST reset it to point to null, otherwise you can crash the program or get a memory leak.
4) A 256 color Bitmap has 1 byte per pixel, but this byte is a palette index, not a color. So you need to convert colors into palette indexs before setting the array. The same applies to 16bit HiColor bitmaps. Fortunately, TrueColor (24bit) images are the actual colors, although you need to set each RGB byte individually.
5) Oddly enough, the array is mapped from the bottom up. In other words, array point 0, 0 is the BOTTOM left corner.

After you are done, you must reset the array. Here is how you can do it:
Code:
Public Sub ReleaseData(a() As Byte)
CopyMemory ByVal VarPtrArray(a), 0&, 4
End Sub
So now how do you use the array?

Well, the array is now a 2D array of the form Data(X, Y) where X is the column and Y is the row. Each element of the array is a byte. For 256 color bitmaps, this byte is a palette index for that pixel. But for 24 bit images, each byte is a colour value (BGR) for a pixel, so each pixel consists of 3 consecutive bytes. eg a 100pixel by 100 pixel image would generate an array 300x100 in size.

Since the array can vary in size, you have to take that into account when making functions to set or read a pixel. For instance:

Code:
Public Sub DrawPixel(Data() As Byte, ByVal x&, ByVal y&, ByVal c&)
Select Case mvarBytesPerPixel
Case 1: Data(x, y) = c And &HFF
Case 2
Data(x + x, y) = (c \ 256) And &HFF
Data(x + x + 1, y) = c And &HFF
Case 3
Data(x * 3, y) = (c \ 65536) And &HFF
Data(x * 3 + 1, y) = (c \ 256) And &HFF
Data(x * 3 + 2, y) = c And &HFF
End Select
End Sub

Public Function ReadPixel(Data() As Byte, ByVal x&, ByVal y&) As Long
Select Case mvarBytesPerPixel
Case 1: ReadPixel = Data(x, y)
Case 2: ReadPixel = Data(x + x, y) * 256& + Data(x + x + 1, y)
Case 3: ReadPixel = ((Data(x * 3, y) * 256&) + Data(x * 3 + 1, y)) * 256& + Data(x * 3 + 2, y)
End Select
End Function
Here is a comparison of speed.

With a 100x100 24 bit bitmap loaded, I set each and every pixel to red using DMA, SetPixel and PSet. The time results were 5ms, 60ms and 550ms respectively. After compiling, the speeds were 4 ms, 50 ms and 70ms. So DMA was around 12x faster than SetPixel.

I've attached a class module to encapsulate the technique. Just compile the class into an ActiveX DLL and then reference it in your own projects. Here is my speed test program that demonstrates how to use this DLL:

Code:
Option Explicit
Private Declare Function GetPixel Lib "gdi32" _
(ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function SetPixel Lib "gdi32" _
(ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Dim pa As BCHPicArray.clsPicArray

Private Sub Command1_Click()
Dim x&, y&, t&
t = timeGetTime()
For y = 0 To Picture1.ScaleHeight - 1
For x = 0 To Picture1.ScaleWidth - 1
pa.DrawPixel x, y, vbRed
Next x
Next y
t = timeGetTime() - t
Picture1.Refresh
Me.Caption = "PicArray=" & t
t = timeGetTime()
For y = 0 To Picture1.ScaleHeight - 1
For x = 0 To Picture1.ScaleWidth - 1
SetPixel Picture1.hdc, x, y, vbRed
Next x
Next y
t = timeGetTime() - t
Picture1.Refresh
Me.Caption = Me.Caption & " SetPixel=" & t
t = timeGetTime()
For y = 0 To Picture1.ScaleHeight - 1
For x = 0 To Picture1.ScaleWidth - 1
Picture1.PSet (x, y), vbRed
Next x
Next y
t = timeGetTime() - t
Picture1.Refresh
Me.Caption = Me.Caption & " PSet=" & t
End Sub

Private Sub Form_Load()
Set pa = New clsPicArray
pa.LoadPicArray Picture1.Picture
End Sub

Private Sub Form_Unload(Cancel As Integer)
Set pa = Nothing
End Sub

Friday, December 8, 2006

How to load a dynamic link library (DLL) into a Microsoft Visual C++ 6.0 project

Steps to perform:

  • Create in Microsoft Visual C++ 6.0 an MFC application (.dll or .exe);
  • Go to the menu View, ClassWizard.
  • Select an option Add Class…, from a type library.
  • Browse to the location of your *.dll.
  • A window, which displays the content of your *.dll, will appear. Select all classes you want to include in your project (Ctrl+A – select all content, or Ctrl + mouse click – for selecting a specific set of classes).
  • Push the button Open. Header file *.h and *.cpp implementation file will be generated.
  • Close the ClassWizard.

Now, all services you selected for use in you project are available!

Wednesday, December 6, 2006

Good day

Good day people i would be posting tutorial on this blog. if you have any request on any programming tutorial. please leave a message and i will try my best to post that tutorial. thank you

Saturday, December 2, 2006

Object Oriented Programming

Take advantage of C# 2.0 platform advances by creating and using anonymous methods

C# developers are familiar with using delegates and named methods to implement a wide range of functionality, most notably events. With C# 2.0, Microsoft has introduced a new way to declare a delegate and the associated method called "anonymous methods." Zach Smith explains what anonymous methods are, and how to use them

News From http://uk.builder.com/architecture/oop/

Friday, December 1, 2006

Internet TV for Free!?


Ever wanted to watch tv at your pc for free without buying any hardware?

All you need to have is a high speed internet connection.
And the software, TVU Player yes it is free.

What is TVU Player? it is a free tv software made by TVU Network and uses bittorrent technology to stream their tv channels.

anyway here is the link where you can download the software. Click Here

Wednesday, November 29, 2006

How do I do it in VB.NET?

This tutorial explain some of the more common migrating problems from VB to VB.NET.
  • DoEvents

    VB6
    DoEvents

    VB7
    System.Windows.Forms.Application.DoEvents
  • App Object

    Get the full application filepath

    VB6
    App.Path & App.EXEName

    VB7 System.Reflection.Assembly.GetExecutingAssembly.Location.ToString

    Get the app's instance

    VB6 App.hInstance

    VB7
    System.Runtime.InteropServices.Marshal.GetHINSTANCE _(System.Reflection.Assembly.GetExecutingAssembly.GetModules() _(0)).ToInt32()

    Check for a previous instance

    VB6
    App.PrevInstance

    VB7
    Function PrevInstance() As Boolean
    If Ubound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess).ProcessName)) > 0 Then
    Return True
    Else
    Return False
    End If

    End Sub
  • Graphics

    Load a picture

    VB6
    Picture1.Picture = LoadPicture(path)

    VB7
    Dim img As Image = Image.FromFile(path)
    Picture1.Image = img

    Load a icon

    VB6
    Me.Icon = LoadPicture(path)

    VB7
    Dim ico As New Icon(path)
    Me.Icon = ico

  • File I/0

    Read from a file

    VB6
    Open path For Input As #1
    Line Input #1, buffer
    Close #1

    VB7
    Dim fs As FileStream = File.Open(path, FileMode.OpenOrCreate, _ FileAccess.Read)
    Dim sr As New StreamReader(fs)
    Buffer = sr.ReadLine
    sr.Close

    Write to a file

    VB6
    Open path For Output As #1
    Write #1, buffer
    Close #1


    VB7
    Dim fs As FileStream = File.Open(path, FileMode.OpenOrCreate, _
    FileAccess.Write)
    Dim sr As New StreamWriter(fs)
    sr.Write(buffer)
    sr.Close

  • Errors

    Check for an error


    VB6
    On Error Goto errhandler
    ...
    errhandler:
    MsgBox(err.Description)

    VB7
    Try
    ...
    Throw New Exception("error description goes here")
    ...
    Catch e as Exception
    MsgBox(e.Description)
    End Try

  • Events

    Handling an event

    In VB7, there is a new keyword called AddHandler. AddHandler makes handling events a snap.

    AddHandler object.event, AddressOf procedure

Monday, November 27, 2006

C++ Intro…

Before you write your first program. Start with a prayer to God, that you “Succeed in learning C++”.

Now that all your hopes are high let us start. Please enter the following code exactly as shown, without any questions. (This is to inform you that the explanation will follow after the code.)

  1. #include
  2. int main()
  3. {
  4. cout<< “ What you do is what you get”;
  5. }

Although this may sound strange, once you compile this program you are a programmer.

<Warning: The numbered indentation is not to be included with the code while typing. It is only for your convenience>

Now let us read the first line. You read it as “Hash/Pound include eye-oh-stream-dot-h”

Iostream: Input Output stream. Don’t learn the definitions they automatically come to you.

You don’t pronounce the brackets while reading it loud, but is it a part of the code.

.h: Dot h files are known as header files. We place them in the beginning of the source code; it is like adding a DVD-Player to your deck. You don’t create .h files for now, nor would you add a DVD-Player to your deck each time you want to use it.

Iostream.h: Ok now you know what iostream and dot h stand for. If the terms input & output haven’t shed any light yet, keep reading. Iostream lets your program accept info/data/content or publish the same to the screen.

Wait we are still on the first line. Read the first line of source code again!

“Hash/Pound include eye-oh-stream-dot-h”

The Hash include is the standard form for telling the compiler that you want to include the Iostream.h file.

Now on line 2 we have int main(). Int is read as integer, read main() as main function. Without line 2 your program cannot work. On line 3 and 5 you have these {} braces.

Between the 2 braces all your code fits in. Make sure you enter line 4 exactly as it is. Pay attention to the punctuation.

Cout: See cout – It is the command with which you display text onto the screen

The <<>

Line 4 ends with a semi colon, don’t forget to type that, almost all c++ statements end with that. Now you may finally link, build and compile the code. Now you receive a message on a black terminal (Dos like): “What you do is what you get”


By: Amin Patel

Sunday, November 26, 2006

Open Read/Write File Code Download

i've decided to upload a sample code of my two previous post.

to download the code please click here
the password is: kodekruncher

Saturday, November 25, 2006

VB: Open Save File

Public Function SaveFile(File2Save As String, txtContent As String)

'Variable Declaration
Dim fLen As Integer

'Get the free file number
fLen = FreeFile

'Create Specified File
Open File2Save For Output As #fLen
Print #fLen, txtContent 'save the txtContent to the created file
Close #fLen 'Close the opened

End Function

Friday, November 24, 2006

VB: Open Read File



Public Function
 ReadFile(File2Open As String) As String

'Variable Declaration
Dim fLen As Integer
Dim tmp As String
Dim val As String

'Get the free file number
fLen = FreeFile

'Open Specified declared in File2Open Variable
Open File2Open For Input As #fLen
        
        Do ' Start of "DO" Loop
                Line Input #fLen, tmp ' Read the line in a file and store it in TMP Variable
                val = val & vbCrLf & tmp ' Store the readed line in the Val variable
        Loop Until EOF(fLen) 'End Loop until Eof file is True

Close #fLen ' Close the opened file

ReadFile = val ' pass value

End Function

Thursday, November 23, 2006

Welcome to The Code Cruncher

This Blog is all about programming and and i will be sharing some code that I made and some code that i would find intresting and usefull. Hope you guys will find this blog usefull

Programming Codes that would be posted here are.

  • Visual Basic
  • Visual Basic.Net
  • ASP / ASP.NET
  • Visual C#/ C++ /C
  • Java
  • Pascal
  • ASM
.

Google Search