Author Topic: Windows Experience.  (Read 22837 times)

0 Members and 1 Guest are viewing this topic.

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Windows Experience.
« on: October 07, 2008 »
Hello out there,

I am fairly new to creating windows apps; know just about the basics, and have made a framework from looking at the Freebasic examples folder; and put in support for loading 8Bit images using Rbz's Bmp2Raw & Bin2Bas.

My aim for the future is to create a skinable application with button; these I beileve are drawn using 4 positions of a rectangles and a region. As discovered in an earlier topic about having some problems with running and compiling into the examples folders with windows vista 32-bit, from Jim.

First I'd like to know if im going about setting up the bmp / image correctly. Im not entirely sure where I should be putting my graphic loading stuff; I had thought of putting it into the WM_Create case statement, but I dont think thats right as the image will be created each loop of that function; unless I am mistaken and it only cycles that part once.

I want to keep the gfxbuffer pointer type as is thanks, and im fully aware that I may have to send it via the subs / functiuon calls,. as I have found that it can't be made Global ( Shared ). Also I may need to add other elements to the type.

I am not entirely sure if the drawgfxbuffer routine will work either and where that should go in the wndproc function, and at present it has no positioning. Also dont understand these settings:   .biXPelsPerMeter  = 75,
.biYPelsPerMeter  = 75

Another concern is how to get the HWnd and feed it to the sub for the SetDIBitsToDevice.

I know there's quite a few queries and bits i am stuck on, and any assistance and help fixing and pointing out the problems / solutions is very much appreciated.

Hope that I've made enough sense.

Please find attached win framework and image data,
Cheers and huge thanks,

Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #2 on: October 07, 2008 »
Ok thanks Jim, I must of missed something on that link, as most of them talk about not liking skinned windows.

My first problem is dealing with displaying images; not entirely sure where I should be putting that etc, and how wndproc works? I've noticed that some people put media into WM_Create; but doesnt that reload the data each time?

Cheers,
Clyde
« Last Edit: October 07, 2008 by Clyde »
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Windows Experience.
« Reply #3 on: October 07, 2008 »
Quote
some people put media into WM_Create; but doesnt that reload the data each time?
depends on how often you create your window ;)

Quote
a skinable application with button; these I beileve are drawn using 4 positions of a rectangles
A single button is indeed easy. It's getting more interessting when you have a complex user-interface with hierarchical structures and subframes.
Here you need some sort of layouting-mechanism which dynamically assigns the available space to the different elements.
Better invest some thoughts into that before starting anything.
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #4 on: October 10, 2008 »
I think it would be quicker, if the window was only created once.

And as I've not dealt with windows before; apart from the framework which I adapted from the examples with FB21. I would really appreciate some help in getting me started in drawing images onto a window.

Cheers and many thanks,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Windows Experience.
« Reply #5 on: October 10, 2008 »
I've fixed up your framework to draw the graphic you supplied (not much to look at).
WndProc gets called with WM_CREATE only once, so you can load all your stuff there.
WM_PAINT gets called every time Windows wants to repaint the window (usually if it gets uncovered, comes back on the screen, gets restored, etc).  If you want static stuff, that's all you need to do.  If you want animating stuff, we can arrange for a timer to go off regularly which can, in turn, make WM_PAINT get called.  This is what I'm doing in my retro-remake to get 50Hz.

Code: [Select]
'
' Clyde Gets Into Windows.
' October 2008
'
Option Explicit

#Include Once "Windows.bi"
#Include Once "crt.bi"

#Include Once "media\FaceP.bas"
#Include Once "media\FaceR.bas"

Const XRES=640
Const YRES=480
Const APPNAME  As String="Windows Framework"

Type GfxBuffer
    wwidth As Integer
    height As Integer
    pixels As UInteger pointer
End Type

Declare Sub DrawGfxBuffer( ByVal hdc   As HDC,_
                           ByVal Source As GfxBuffer Pointer )

Declare Function CreateGFXBuffer( Byval WWidth As Integer,_
                                  Byval Height As integer ) As GfxBuffer Pointer
                                 
Declare Function LoadGraphics8Bit( ByVal WWidth As Integer,_
                                   ByVal Height As Integer,_
                                   ByVal Raw    As UByte Pointer,_
                                   ByVal Palet  As UByte Pointer ) As GfxBuffer Pointer

Declare Function WndProc ( ByVal hWnd       As HWND,_
                           ByVal message    As UINT,_
                           ByVal wParam     As WPARAM,_
                           ByVal lParam     As LPARAM ) As LRESULT


Declare Function WinMain ( ByVal hInstance      As HINSTANCE,_
                           ByVal hPrevInstance  As HINSTANCE,_
                           ByRef szCmdLine      As String,_
                           ByVal iCmdShow       As Integer ) As Integer   

'
' Load Graphics into pointers types.
'
Dim As GfxBuffer Pointer TestImage=LoadGraphics8Bit( 32, 32, @FaceR(0), @FaceP(0) )


WinMain( GetModuleHandle( Null ), Null, Command, SW_NORMAL )
End



Sub DrawGfxBuffer(ByVal hdc as HDC, ByVal Source As GfxBuffer Pointer )

    Dim bmi As BITMAPINFO

    With bmi.bmiheader
   
        .biSize           = SizeOf (BITMAPINFOHEADER)
        .biWidth          =  Source->WWidth
        .biHeight         = -Source->Height
        .biPlanes         = 1
        .biBitCount       = 8
        .biCompression    = BI_RGB
        .biSizeImage      = 0
        .biXPelsPerMeter  = 75
        .biYPelsPerMeter  = 75
        .biClrUsed        = 0
        .biClrImportant   = 0
   
    End With

   
    SetDIBitsToDevice(hdc, 0,0, Source->WWidth, Source->Height, 0, 0, 0, Source->Height, @Source->Pixels[0], @bmi,

DIB_RGB_COLORS)

End Sub

dim shared as GfxBuffer Pointer myGfx


Function CreateGFXBuffer( Byval WWidth As Integer,_
                          Byval Height As Integer ) As GfxBuffer Pointer
   
    Dim As GfxBuffer Pointer Buffer=Callocate(Len( GfxBuffer )+Len( UInteger )*WWidth*Height)
   
    Buffer->wwidth=WWidth
    Buffer->height=Height
    Buffer->pixels=Cast( UInteger Pointer, Cast( Byte Pointer, Buffer )+Len( GfxBuffer ))
   
    Function=Buffer
   
End Function


Function WndProc ( ByVal hWnd       As HWND,_
                   ByVal message    As UINT,_
                   ByVal wParam     As WPARAM,_
                   ByVal lParam     As LPARAM ) As LRESULT

    Dim As PAINTSTRUCT Render
    Dim As HDC hDC
 
    Select Case ( message )
       
        Case WM_CREATE           
           
            myGfx = LoadGraphics8bit(32,32,@facer(0),@facep(0))
           
            Function=0
       
        Case WM_PAINT
         
            hDC = BeginPaint( hWnd, @Render )
            DrawGfxBuffer(hdc, myGfx)
            EndPaint( hWnd, @Render )
            Function=0
       
        Case WM_KEYDOWN

            Select Case LoByte( wParam )

                Case VK_ESCAPE
                    PostMessage( hWnd, WM_CLOSE, 0, 0 )
                    Function=0
       
            End Select

        Case WM_DESTROY
   
            PostQuitMessage( 0 )
            Function=0
   
    End Select
   
    Function=DefWindowProc( hWnd, message, wParam, lParam )   
   
End function


Function WinMain ( ByVal hInstance      As HINSTANCE,_
                   ByVal hPrevInstance  As HINSTANCE,_
                   ByRef szCmdLine      As String,_
                   ByVal iCmdShow       As Integer ) As Integer   
     
    Dim wMsg        As MSG
    Dim wClass      As WNDCLASS     
    Dim hWnd        As HWND

    Function = 0
     
    With wClass
    .style         = CS_HREDRAW or CS_VREDRAW
      .lpfnWndProc   = @WndProc
      .cbClsExtra    = 0
      .cbWndExtra    = 0
      .hInstance     = hInstance
      .hIcon         = LoadIcon( null, IDI_APPLICATION )
      .hCursor       = LoadCursor( null, IDC_ARROW )
      .hbrBackground = GetStockObject( BLACK_BRUSH )
      .lpszMenuName  = null
      .lpszClassName = StrPtr( APPNAME )
    end with
     
    If( RegisterClass( @wClass ) = False ) Then
        Exit Function
    End If

    hWnd = CreateWindowEx( 0,_
                           APPNAME,_
                           APPNAME,_
                           WS_OVERLAPPEDWINDOW, _
                           CW_USEDEFAULT,_
                           CW_USEDEFAULT,_
                           XRES,_
                           YRES,_
                           null,_
                           null,_
                           hInstance,_
                           null )
                         
    ShowWindow( hWnd, iCmdShow )
    UpdateWindow( hWnd )
     
    While ( GetMessage( @wMsg, null, 0, 0 ) <> False )   
        TranslateMessage( @wMsg )
        DispatchMessage ( @wMsg )
    Wend
   
    Function = wMsg.wParam

End Function


Function LoadGraphics8Bit( ByVal WWidth  As Integer,_
                           ByVal Height  As Integer,_
                           ByVal Raw     As UByte Pointer,_
                           ByVal Palet   As UByte Pointer ) As GfxBuffer Pointer
   
    Dim As GfxBuffer Pointer Buffer=CreateGFXBuffer( WWidth, Height )

    Dim As UInteger pal(0 to 255)
    Dim As Integer a,x,y

    '
    ' Retrieve Palette Info.
    '
    For a=0 to 255
        pal(a)=(palet[a*3] Shl 16) Or (palet[a*3+1] Shl 8) Or(palet[a*3+2])
    Next   
   
    '
    ' Make Image Based On Colour Indexing With The Raw values.
    '
    For y=0 to Height-1
        For x=0 to WWidth-1
            Buffer->Pixels[ x+y*WWidth ]=Pal(Raw[x+y*WWidth])
        Next
    Next
   
    Function=Buffer
   
End Function

<edit>
Quote
.biXPelsPerMeter  = 75
This is just setting the dpi (dots per inch) for the bitmap.  Really only useful if you're intending to print it on a printer.  75 is a sensible default.  If you are trying for tiny code then 0 might also work.

Jim
« Last Edit: October 10, 2008 by Jim »
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #6 on: October 11, 2008 »
Thankyou so much mate.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #7 on: October 13, 2008 »
Only problem is, after properly using it, that the image isn't appearing as should be see below for actual image.
Also the myGFX should be Dimmed as a GFXBuffer pointer, but this crashes the window.

Not entirely sure on the calls from

Code: [Select]
SetDIBitsToDevice(hdc, 0,0, Source->WWidth, Source->Height, 0, 0, 0, Source->Height, @Source->Pixels[0], @bmi,
I think the 4th entry where it has, Source->WWidth - Should be Image Position X
And the 5th entry should be for image position y.


[ edit ]
I have added an update to the code Im fiddling with, I get graphics / variable name errors. if I put the the image dim bits out of the select case loop, it doesnt give errors. Which isnt the way forward, I dont think.

Code: [Select]
'
' Clyde Gets Into Windows.
' October 2008
'
Option Explicit

#Include Once "Windows.bi"
#Include Once "crt.bi"

#Include Once "media\FaceP.bas"
#Include Once "media\FaceR.bas"

Const XRES=640
Const YRES=480
Const APPNAME  As String="Windows Framework"

Type GfxBuffer
    wwidth As Integer
    height As Integer
    pixels As UInteger pointer
End Type


Declare Sub DrawGfxBuffer( ByVal hdc as HDC,_
                           ByVal Source As GfxBuffer Pointer,_
                           ByVal PosX As Integer,_
                           ByVal PosY As Integer )


Declare Function CreateGFXBuffer( Byval WWidth As Integer,_
                                  Byval Height As integer ) As GfxBuffer Pointer
                                 
Declare Function LoadGraphics8Bit( ByVal WWidth As Integer,_
                                   ByVal Height As Integer,_
                                   ByVal Raw    As UByte Pointer,_
                                   ByVal Palet  As UByte Pointer ) As GfxBuffer Pointer

Declare Function WndProc ( ByVal hWnd       As HWND,_
                           ByVal message    As UINT,_
                           ByVal wParam     As WPARAM,_
                           ByVal lParam     As LPARAM ) As LRESULT


Declare Function WinMain ( ByVal hInstance      As HINSTANCE,_
                           ByVal hPrevInstance  As HINSTANCE,_
                           ByRef szCmdLine      As String,_
                           ByVal iCmdShow       As Integer ) As Integer   

WinMain( GetModuleHandle( Null ), Null, Command, SW_NORMAL )
End



Sub DrawGfxBuffer( ByVal hdc as HDC,_
                   ByVal Source As GfxBuffer Pointer,_
                   ByVal PosX As Integer,_
                   ByVal PosY As Integer )

    Dim bmi As BITMAPINFO

    With bmi.bmiheader
   
        .biSize           = SizeOf (BITMAPINFOHEADER)
        .biWidth          =  Source->WWidth
        .biHeight         = -Source->Height
        .biPlanes         = 1
        .biBitCount       = 8
        .biCompression    = BI_RGB
        .biSizeImage      = 0
       ' .biXPelsPerMeter  = 75
       ' .biYPelsPerMeter  = 75
        .biClrUsed        = 0
        .biClrImportant   = 0
   
    End With

    'SetDIBitsToDevice(hdc, 0,0, Source->WWidth, Source->Height, 0, 0, 0, Source->Height, @Source->Pixels[0], @bmi, DIB_RGB_COLORS)
    SetDIBitsToDevice(hdc, 0,0, PosX, PosY, 0, 0, 0, Source->Height, @Source->Pixels[0], @bmi, DIB_RGB_COLORS)

End Sub


Function CreateGFXBuffer( Byval WWidth As Integer,_
                          Byval Height As Integer ) As GfxBuffer Pointer
   
    Dim As GfxBuffer Pointer Buffer=Callocate(Len( GfxBuffer )+Len( UInteger )*WWidth*Height)
   
    Buffer->wwidth=WWidth
    Buffer->height=Height
    Buffer->pixels=Cast( UInteger Pointer, Cast( Byte Pointer, Buffer )+Len( GfxBuffer ))
   
    Function=Buffer
   
End Function


Function WndProc ( ByVal hWnd       As HWND,_
                   ByVal message    As UINT,_
                   ByVal wParam     As WPARAM,_
                   ByVal lParam     As LPARAM ) As LRESULT

    Dim As PAINTSTRUCT Render
    Dim As HDC hDC
   

    Select Case ( message )
       
        Case WM_CREATE           
           
            Dim As GfxBuffer Pointer Image1= LoadGraphics8bit(32,32,@facer(0),@facep(0))
           
            Function=0
       
        Case WM_PAINT
         
            hDC = BeginPaint( hWnd, @Render )
           
                DrawGfxBuffer(hdc, Image1, 100, 100)
           
           
            EndPaint( hWnd, @Render )
            Function=0
       
        Case WM_KEYDOWN

            Select Case LoByte( wParam )

                Case VK_ESCAPE
                    PostMessage( hWnd, WM_CLOSE, 0, 0 )
                    Function=0
       
            End Select

        Case WM_DESTROY
   
            PostQuitMessage( 0 )
            Function=0
   
    End Select
   
    Function=DefWindowProc( hWnd, message, wParam, lParam )   
   
End function


Function WinMain ( ByVal hInstance      As HINSTANCE,_
                   ByVal hPrevInstance  As HINSTANCE,_
                   ByRef szCmdLine      As String,_
                   ByVal iCmdShow       As Integer ) As Integer   
     
    Dim wMsg        As MSG
    Dim wClass      As WNDCLASS     
    Dim hWnd        As HWND

    Function = 0
     
    With wClass
    .style         = CS_HREDRAW or CS_VREDRAW
      .lpfnWndProc   = @WndProc
      .cbClsExtra    = 0
      .cbWndExtra    = 0
      .hInstance     = hInstance
      .hIcon         = LoadIcon( null, IDI_APPLICATION )
      .hCursor       = LoadCursor( null, IDC_ARROW )
      .hbrBackground = GetStockObject( BLACK_BRUSH )
      .lpszMenuName  = null
      .lpszClassName = StrPtr( APPNAME )
    end with
     
    If( RegisterClass( @wClass ) = False ) Then
        Exit Function
    End If

    hWnd = CreateWindowEx( 0,_
                           APPNAME,_
                           APPNAME,_
                           WS_OVERLAPPEDWINDOW, _
                           CW_USEDEFAULT,_
                           CW_USEDEFAULT,_
                           XRES,_
                           YRES,_
                           null,_
                           null,_
                           hInstance,_
                           null )
                         
    ShowWindow( hWnd, iCmdShow )
    UpdateWindow( hWnd )
     
    While ( GetMessage( @wMsg, null, 0, 0 ) <> False )   
        TranslateMessage( @wMsg )
        DispatchMessage ( @wMsg )
    Wend
   
    Function = wMsg.wParam

End Function


Function LoadGraphics8Bit( ByVal WWidth  As Integer,_
                           ByVal Height  As Integer,_
                           ByVal Raw     As UByte Pointer,_
                           ByVal Palet   As UByte Pointer ) As GfxBuffer Pointer
   
    Dim As GfxBuffer Pointer Buffer=CreateGFXBuffer( WWidth, Height )

    Dim As UInteger pal(0 to 255)
    Dim As Integer a,x,y

    '
    ' Retrieve Palette Info.
    '
    For a=0 to 255
        pal(a)=(palet[a*3] Shl 16) Or (palet[a*3+1] Shl 8) Or(palet[a*3+2])
    Next   
   
    '
    ' Make Image Based On Colour Indexing With The Raw values.
    '
    For y=0 to Height-1
        For x=0 to WWidth-1
            Buffer->Pixels[ x+y*WWidth ]=Pal(Raw[x+y*WWidth])
        Next
    Next
   
    Function=Buffer
   
End Function

[ Image Info ] Can be found in first topic download [ / Image Info ]


Cheers and many thanks,
Clyde
« Last Edit: October 13, 2008 by Clyde »
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #8 on: October 13, 2008 »
Ok, cured it for now. For some reason, even though the image is an 8bit ( 256 colours ), the bitcount needs to be 32bit. And I've found a solution to my varables for holding images conundrum.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #9 on: October 13, 2008 »
Before I carry on, and ask about skinable windows, and button events ( Regions? ).
Is there some info I can get see to what SetDIBitsToDevice() actually represents, and also any info on bmpheaders? Also if one of the fields isn't greater than 0, will there be any problems in not defining it ( leaving it out ) ?

Cheers,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Windows Experience.
« Reply #10 on: October 13, 2008 »
Obviously you can't declare the gfx variables inside the WM_CREATE part, you have to make them global.  Just like any other function they won't hang around until the next time it's called.
I missed the fact you'd changed the bits to 8.  In this code here
Code: [Select]
For a=0 to 255
        pal(a)=(palet[a*3] Shl 16) Or (palet[a*3+1] Shl 8) Or(palet[a*3+2])
    Next   
   
    '
    ' Make Image Based On Colour Indexing With The Raw values.
    '
    For y=0 to Height-1
        For x=0 to WWidth-1
            Buffer->Pixels[ x+y*WWidth ]=Pal(Raw[x+y*WWidth])
        Next
    Next
you are loading the 32bit palette, all 256 colours, and then for each raw pixel you are looking it up in the palette, ie. you've converted it to 32 bit.
Quote
Is there some info I can get see to what SetDIBitsToDevice()
Sure. http://msdn.microsoft.com/en-us/library/ms532346(VS.85).aspx
Quote
Also if one of the fields isn't greater than 0, will there be any problems in not defining it ( leaving it out ) ?
Yes.  You need to define things.  You might be able to memset it to 0 or declare it as a global which will make sure it's all 0s by default.  If you declare it on the stack (local variable) it will be full of junk every time.
I strongly suggest getting it all working before trying stuff like that anyway.

Jim

Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #11 on: October 13, 2008 »
Ok cool, thanks Jim. The SetDiBitsToDevice, works a bit like DrawImageRectangle ( in parts ) from Blitz.

Also had forgotten the palete and raw was being converted to 32-bit.

Next question is: How would I go about setting up a button made from an image, and then have the mouse go over it and it changes to another image; and if it's clicked performs an action ?

Cheers,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Windows Experience.
« Reply #12 on: October 13, 2008 »
What I would do is create a type called BUTTON that holds all the information about a button, that might be:
x,y - position of button
sprite1 - normal sprite
sprite2 - selected sprite
buttonstate - whether button is selected or not

Then I'd write a function to create them from filenames and positions.
Then I'd write a function called IsMouseOverButton
delcare function IsMouseOverButton(btn as BUTTON, mousex as integer, mousey as integer) as boolean
which would find out if the mousexy is inside the button.
Then I'd have an array of buttons which I checked every time the mouse moved.

When the mouse moves, you get a WM_MOUSEMOVE message
http://msdn.microsoft.com/en-us/library/ms645616(VS.85).aspx
Code: [Select]
case WM_MOUSEMOVE
  dim mousex as integer
  dim mousey as integer
  mousex = lParam and &Hffff
  mousey = lParam shr 16
After that I'd check if mousex/mousey was over any of my buttons.

Then, you might need to force the window to repaint, if one of the buttons was hovered over.
To do that, call
InvalidateRect(hWnd, NULL, FALSE)
http://msdn.microsoft.com/en-us/library/ms534893(VS.85).aspx

Finally, I'd change WM_PAINT to run through all the buttons and draw them all.

Jim
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #13 on: October 13, 2008 »
I'll get cracking with this, some of it, I will have to ask you about. My first question is what is the data type for the boolean on this: IsMouseOverButton(btn as BUTTON, mousex as integer, mousey as integer) as boolean

Cheers,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #14 on: October 14, 2008 »
Ok after having a look around mostly in the examples folders, also at Rbz's Camouflage music disk and your advice Jim. I have managed to get a very simple and primitive example of my own.

A few things, is how to use a sound scheme if it is enabled on the pc, and I'd also like to have the arrow icon change to a hand if the button performs a task. Also, what would be nice is to have a text field show, when hovering over a particular button.

And another concern is why the background plasma effect doesnt update properlly. Maybe it's in the wrong place, a bit weird that it doesnt move at all. You did mention something about timers; will see if I can find anything on that; still would like some pointers on that.

Heres the code so far:
Code: [Select]
'
' Clyde Gets Into Windows.
' October 2008
'
Option Explicit

#Include Once "Windows.bi"
#Include Once "crt.bi"

#Include Once "media\FaceP.bas"
#Include Once "media\FaceR.bas"

#Include Once "media\Face2P.bas"
#Include Once "media\Face2R.bas"


Const As Single PI=3.14159265
Const As Single D2R=PI/180.0

Const MAXBUTTONS=2
Const XRES=640
Const YRES=480
Const APPNAME  As String="Windows Framework"

Type GfxBuffer
    wwidth As Integer
    height As Integer
    pixels As UInteger pointer
End Type

Type Button
   
    Region  As HRGN
   
    Rect As RECT
 
    PosX    As Integer
    PosY    As Integer
    Image1  As GFXBuffer Pointer
    Image2  As GFXBuffer Pointer
    State   As Integer
End Type
   

Dim Shared As GfxBuffer Pointer Image1,Image2, ScreenBuffer, Palette1
Dim Shared As Button Pointer Button( 0 To MAXBUTTONS-1 )

Dim Shared As Single Cosine( 0 to 1500 )
Dim Shared As Integer wave1,wave2,wave3

Declare Sub InitializeWindows()


Declare Sub UpdatePlasma( ByVal Pal             As GFXBuffer Pointer,_
                          ByVal ScreenBuffer    As GFXBuffer Pointer,_
                          ByVal Val1            As Integer,_
                          ByVal Val2            As Integer,_
                          ByVal Val3            As Integer )

Declare Sub DrawButton( ByVal hdc as HDC,_
                        ByVal Buton As Button Pointer )

Declare Sub DrawGfxBuffer( ByVal hdc as HDC,_
                           ByVal Source As GfxBuffer Pointer,_
                           ByVal PosX As Integer,_
                           ByVal PosY As Integer )

Declare Function CreateButton( ByVal Image1 As GFXBuffer Pointer,_
                               ByVal Image2 As GFXBuffer Pointer,_
                               ByVal StartPosX As Integer,_
                               ByVal StartPosY As Integer ) As Button Pointer

Declare Function CreateButtonRegion( ByVal PosX0 As Integer,_
                                     ByVal PosY0 As Integer,_
                                     ByVal PosX1 As Integer,_
                                     ByVal PosY1 As Integer) As HRGN


Declare Function CreateGFXBuffer( Byval WWidth As Integer,_
                                  Byval Height As integer ) As GfxBuffer Pointer
                                 


Declare Function CreatePalettes( ByVal WWidth As Integer,_
                                 ByVal Height As Integer,_
                                 ByVal Val1   As Integer,_
                                 ByVal Val2   As Integer,_
                                 ByVal Val3   As Integer,_
                                 ByVal Divv   As Integer=360) As GFXBuffer Pointer

                                 
Declare Function LoadGraphics8Bit( ByVal WWidth As Integer,_
                                   ByVal Height As Integer,_
                                   ByVal Raw    As UByte Pointer,_
                                   ByVal Palet  As UByte Pointer ) As GfxBuffer Pointer

Declare Function WndProc ( ByVal hWnd       As HWND,_
                           ByVal message    As UINT,_
                           ByVal wParam     As WPARAM,_
                           ByVal lParam     As LPARAM ) As LRESULT


Declare Function WinMain ( ByVal hInstance      As HINSTANCE,_
                           ByVal hPrevInstance  As HINSTANCE,_
                           ByRef szCmdLine      As String,_
                           ByVal iCmdShow       As Integer ) As Integer   

WinMain( GetModuleHandle( Null ), Null, Command, SW_NORMAL )
End



Sub UpdatePlasma( ByVal Pal             As GFXBuffer Pointer,_
                  ByVal ScreenBuffer    As GFXBuffer Pointer,_
                  ByVal Val1            As Integer,_
                  ByVal Val2            As Integer,_
                  ByVal Val3            As Integer )
   
   Dim As Integer x,y,d,f
   
   For y = 0 To ScreenBuffer->Height-1

        d = cosine( y + wave2 ) + cosine( y + wave3 )

        For x = 0 To ScreenBuffer->WWidth-1

            f = cosine( x + wave1 ) + cosine( x + y ) + d and 255
               
            ScreenBuffer->Pixels [ x+y*ScreenBuffer->WWidth ]=Pal->Pixels[ f and 255 ]

        Next

    Next

    wave1 = wave1 + Val1
    If wave1 >= ScreenBuffer->WWidth-1 Then wave1 = wave1 - ScreenBuffer->WWidth

    wave2 = wave2 + Val2
    If wave2 >= ScreenBuffer->WWidth-1 Then wave2 = wave2 - ScreenBuffer->WWidth
   
    wave3 = wave3 + Val3
    If wave3 >= ScreenBuffer->WWidth-1 Then wave3 = wave3 - ScreenBuffer->WWidth
   
End Sub


Function CreateButton( ByVal Image1 As GFXBuffer Pointer,_
                       ByVal Image2 As GFXBuffer Pointer,_
                       ByVal StartPosX As Integer,_
                       ByVal StartPosY As Integer ) As Button Pointer
   
    Dim Btn As Button Pointer=Callocate(Len( Button )+Len( UInteger ))
   
    Btn->PosX=StartPosX
    Btn->PosY=StartPosY
   
    Btn->Image1=Image1
    Btn->Image2=Image2
   
    Btn->State=0
    Btn->Region=CreateButtonRegion( StartPosX,_
                                    StartPosY,_
                                    StartPosX+Btn->Image1->WWidth,_
                                    StartPosY+Btn->Image1->Height )
                                   
    Btn->Rect.left  =StartPosX
    Btn->Rect.top   =StartPosY
    Btn->Rect.right =StartPosX+Btn->Image1->WWidth
    Btn->Rect.bottom=StartPosY+Btn->Image1->Height
   

    Function=Btn
   
End Function


Function CreateButtonRegion( ByVal PosX0 As Integer, ByVal PosY0 As Integer, ByVal PosX1 As Integer, ByVal PosY1 As Integer) As HRGN
   
    Dim Region As HRGN
   
    Region=CreateRectRgn( PosX0,_   ' x-coordinate of region's upper-left corner
                          PosY0,_   ' y-coordinate of region's upper-left corner
                          PosX1,_   ' x-coordinate of region's lower-right corner 
                          PosY1 )   ' y-coordinate of region's lower-right corner 
   
    Function=Region
   
End Function


Sub InitializeWindows()
   
    ScreenBuffer = CreateGFXBuffer( XRES, YRES )
   
    Image1= LoadGraphics8bit(32,32,@facer(0),@facep(0))
    Image2= LoadGraphics8bit(32,32,@facer2(0),@facep2(0))
   
    Button(0)=CreateButton( Image1,_
                            Image2,_
                            100,_
                            100)
                           
    Button(1)=CreateButton( Image1,_
                            Image2,_
                            280,_
                            32)
                           
    Palette1=CreatePalettes(1,256,16,128,0)
   
    Dim As Integer a
   
    For a=0 To 1499
        Cosine( a ) = Cos( (( 115*PI * a ) / ScreenBuffer->WWidth )*D2R ) * 128
    Next
   
End Sub


Sub DrawButton( ByVal hdc as HDC,_
                ByVal Buton As Button Pointer )
     
    Select Case As Const Buton->State
   
        Case 0:
        DrawGFXBuffer( hdc, Buton->Image1, Buton->PosX, Buton->PosY )
       
        Case 1:
        DrawGFXBuffer( hdc, Buton->Image2, Buton->PosX, Buton->PosY )
     
    End Select
   
End Sub


Sub DrawGfxBuffer( ByVal hdc as HDC,_
                   ByVal Source As GfxBuffer Pointer,_
                   ByVal PosX As Integer,_
                   ByVal PosY As Integer )

    Dim bmi As BITMAPINFO

    With bmi.bmiheader
   
        .biSize           = SizeOf (BITMAPINFOHEADER)
        .biWidth          =  Source->WWidth
        .biHeight         = -Source->Height
        .biPlanes         = 1
        .biBitCount       = 32
        .biCompression    = BI_RGB
        .biSizeImage      = 0
        .biClrUsed        = 0
        .biClrImportant   = 0
   
    End With

    SetDIBitsToDevice( hdc,_
                       PosX,_
                       PosY,_
                       Source->WWidth,_
                       Source->Height,_
                       0,_
                       0,_
                       0,_
                       Source->Height,_
                       @Source->Pixels[0],_
                       @bmi,_
                       DIB_RGB_COLORS)

End Sub


Function CreatePalettes( ByVal WWidth As Integer,_
                        ByVal Height As Integer,_
                    ByVal Val1   As Integer,_
                    ByVal Val2   As Integer,_
                    ByVal Val3   As Integer,_
                    ByVal Divv    As Integer=360) As GFXBuffer Pointer
   
    Dim As GFXBuffer Pointer Pal=CreateGFXBuffer(WWidth,Height)
   
    Dim As Integer a, red, grn, blu
    Dim As Single m

    For a=0 to 255
       
        m = a*(Divv/255)

        red = cos( (m+Val1)*D2R ) *127+127
        grn = cos( (m+Val2)*D2R ) *127+127
        blu = cos( (m+Val3)*D2R ) *127+127

        Pal->Pixels[ a*Pal->WWidth ] = rgb(red,grn,blu) 

    Next

    Return Pal

End Function



Function CreateGFXBuffer( Byval WWidth As Integer,_
                          Byval Height As Integer ) As GfxBuffer Pointer
   
    Dim As GfxBuffer Pointer Buffer=Callocate(Len( GfxBuffer )+Len( UInteger )*WWidth*Height)
   
    Buffer->wwidth=WWidth
    Buffer->height=Height
    Buffer->pixels=Cast( UInteger Pointer, Cast( Byte Pointer, Buffer )+Len( GfxBuffer ))
   
    Function=Buffer
   
End Function


Function WndProc ( ByVal hWnd       As HWND,_
                   ByVal message    As UINT,_
                   ByVal wParam     As WPARAM,_
                   ByVal lParam     As LPARAM ) As LRESULT

    Dim As PAINTSTRUCT SBuffer
    Dim As HDC hDC
   
    Dim As Integer MouseX, MouseY, a
     
    Select Case ( message )
       
        Case WM_CREATE           
           
            InitializeWindows()
            Function=0
       
        Case WM_PAINT
         
            hDC = BeginPaint( hWnd, @SBuffer )
               
                UpdatePlasma( Palette1, ScreenBuffer, 2, 4, 2 )
               
                DrawGFXBuffer( hdc, ScreenBuffer, 0, 0 )
               
                For a=0 To MAXBUTTONS-1
                    DrawButton( hdc, Button(a) )
                Next
               
            EndPaint( hWnd, @SBuffer )
            Function=0
           
           
        case WM_LBUTTONDOWN
           
            'If Button(0)->State=1 'Then sleep(200)
       
       
        Case WM_MOUSEMOVE
           
            MouseX = LoWord(lParam)' and &Hffff
            MouseY = HiWord(lParam)' shr 16
           
            For a=0 To MAXBUTTONS-1
           
                If (PtInRegion(Button(a)->Region, MouseX, MouseY) <> 0) then
               
                    Button(a)->State=1
                    InvalidateRect(hWnd, @Button(a)->Rect, FALSE)

                Else
               
                    Button(a)->State=0
                    InvalidateRect(hWnd, @Button(a)->Rect, FALSE)

                End if
           
            Next
             
            Case WM_KEYDOWN

            Select Case LoByte( wParam )

                Case VK_ESCAPE
                    PostMessage( hWnd, WM_CLOSE, 0, 0 )
                    Function=0
       
            End Select

        Case WM_DESTROY
   
            PostQuitMessage( 0 )
            Function=0
   
    End Select
   
    Function=DefWindowProc( hWnd, message, wParam, lParam )   
   
End function


Function WinMain ( ByVal hInstance      As HINSTANCE,_
                   ByVal hPrevInstance  As HINSTANCE,_
                   ByRef szCmdLine      As String,_
                   ByVal iCmdShow       As Integer ) As Integer   
     
    Dim wMsg        As MSG
    Dim wClass      As WNDCLASS     
    Dim hWnd        As HWND

    Function = 0
     
    With wClass
    .style         = CS_HREDRAW or CS_VREDRAW
      .lpfnWndProc   = @WndProc
      .cbClsExtra    = 0
      .cbWndExtra    = 0
      .hInstance     = hInstance
      .hIcon         = LoadIcon( null, IDI_APPLICATION )
      .hCursor       = LoadCursor( null, IDC_ARROW )
      .hbrBackground = GetStockObject( BLACK_BRUSH )
      .lpszMenuName  = null
      .lpszClassName = StrPtr( APPNAME )
    end with
     
    If( RegisterClass( @wClass ) = False ) Then
        Exit Function
    End If

    hWnd = CreateWindowEx( 0,_
                           APPNAME,_
                           APPNAME,_
                           WS_OVERLAPPEDWINDOW, _
                           CW_USEDEFAULT,_
                           CW_USEDEFAULT,_
                           XRES,_
                           YRES,_
                           null,_
                           null,_
                           hInstance,_
                           null )
                         
    ShowWindow  ( hWnd, iCmdShow )
    UpdateWindow( hWnd )
     
    While ( GetMessage( @wMsg, null, 0, 0 ) <> False )   
        TranslateMessage( @wMsg )
        DispatchMessage ( @wMsg )
    Wend
   
    Function = wMsg.wParam

End Function


Function LoadGraphics8Bit( ByVal WWidth  As Integer,_
                           ByVal Height  As Integer,_
                           ByVal Raw     As UByte Pointer,_
                           ByVal Palet   As UByte Pointer ) As GfxBuffer Pointer
   
    Dim As GfxBuffer Pointer Buffer=CreateGFXBuffer( WWidth, Height )

    Dim As UInteger pal(0 to 255)
    Dim As Integer a,x,y

    '
    ' Retrieve Palette Info.
    '
    For a=0 to 255
        pal(a)=(palet[a*3] Shl 16) Or (palet[a*3+1] Shl 8) Or(palet[a*3+2])
    Next   
   
    '
    ' Make Image Based On Colour Indexing With The Raw values.
    '
    For y=0 to Height-1
        For x=0 to WWidth-1
            Buffer->Pixels[ x+y*WWidth ]=Pal(Raw[x+y*WWidth])
        Next
    Next
   
    Function=Buffer
   
End Function

« Last Edit: October 14, 2008 by Clyde »
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline DrewPee

  • I Toast Therefore I am
  • Pentium
  • *****
  • Posts: 563
  • Karma: 25
  • Eat Cheese - It's good for you!
    • View Profile
    • Retro Computer Museum
Re: Windows Experience.
« Reply #15 on: October 14, 2008 »
Clyde,
Sorry I can't help! but I do like what you are doing here - very interesting.

DrewPee
DrewPee
aka Falcon of The Lost Boyz (Amiga)
Ex-Amiga Coder and Graphic Designer
Administrator of > www.retrocomputermuseum.co.uk

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17407
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Windows Experience.
« Reply #16 on: October 14, 2008 »
Hmm, that crunches to about 9kb with UPX there Clyde, that's pretty small :)
Thanks for posting what you have done so far, the code is nicely set out too.

It might be nice to get an example of this into the resources section of this web site if you like :)

K+ anyway. Thanks for sharing what you've learned.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #17 on: October 14, 2008 »
Cheers dudess, no problem. It would make for a pretty cool read for people who want to make a music player, or could even create a mini keyboard synthesizer.

What Im stuck with now is in getting the plasma ( and any other effects ) to actually move; for some reason it is staying static. Then I'll be asking some more questions once thats sorted.

Many humble thanks,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Windows Experience.
« Reply #18 on: October 14, 2008 »
You need to ask yourself
When does the plasma get updated?
Answer is in WM_PAINT.
Then, when does WM_PAINT get called?
When the window needs painting because it maxmised, moved, resized, something uncovered it, or you invalidated an area of it using InvalidateRect.
Obviously none of those things happen regularly so nothing gets updated.
What you want is for the whole window to get invalidated regularly so that WM_PAINT gets called regularly.
We can do that with a timer.  Try adding this case in the WndProc:
Code: [Select]
case WM_TIMER
  InvalidateRect(hWnd, NULL, False)

Then, just after you call UpdateWindow in WinMain,
Code: [Select]
SetTimer(hWnd,1,1000/60,NULL)
http://msdn.microsoft.com/en-us/library/ms644906.aspx

That will trigger a WM_TIMER message every 1000/60ms (60Hz) which will, in turn, cause a WM_PAINT message to happen, which will, in turn, cause the plasma to update.

You should probably now remove the InvalidateRgn stuff you put in the button drawing - these also cause WM_PAINT messages to happen and you won't want them now.

Jim
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Windows Experience.
« Reply #19 on: October 14, 2008 »
Jim your a diamond, cheers fella.

When you say remove the invalidateRgn stuff, I think your meaning this in Case WM_MouseMove, 'InvalidateRect(hWnd, @Button(a)->Rect, FALSE).

Or are you meaning elsewhere, and what exactly please dude?

I have also noticed that the 2 buttons flicker now and again ( this happened previously too ). Dont quite know whats a foot with that?

Cheers and huge thanks,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won: