Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: VB6: Aktiivisen ikkunan päällä istuva "maskotti"

Sivun loppuun

Blaze [13.07.2004 23:05:01]

#

Törmäsin tuollaiseen "Love Hina desktop mascot":n ja sattui olemaan tylsä ilta, joten ajattelin tehdä oman vastaavan :)

Luo WinAPIa käyttäen ikkunan, piirtää siihen kuvan ja pitää tuon ikkunan aktiivisen ikkunan päällä. Ks. http://pp.kpnet.fi/blaze/temp/mascot.png

Käyttää layeröityä ikkunaa, joten vaatii Windows 2000:n tai uudemman.

Binääri: http://pp.kpnet.fi/blaze/temp/mascot.zip

Option Explicit

'Vakiot
'RegisterClass
Private Const CS_HREDRAW As Long = &H2&
Private Const CS_VREDRAW As Long = &H1&

'CreateWindow
Private Const WS_POPUP As Long = &H80000000
Private Const WS_VISIBLE As Long = &H10000000

'CreateWindowEx
Private Const WS_EX_LAYERED As Long = &H80000
Private Const WS_EX_TOOLWINDOW As Long = &H80&
Private Const WS_EX_TOPMOST As Long = &H8&
Private Const WS_EX_TRANSPARENT As Long = &H20&

'Viestit
Private Const WM_PAINT As Long = &HF&

'LoadImage
Private Const IMAGE_BITMAP As Long = 0&
Private Const LR_LOADFROMFILE As Long = &H10&

'SetLayeredWindowAttributes
Private Const LWA_COLORKEY As Long = &H1

'Tyypit
Private Type WNDCLASSEX
    cbSize As Long
    style As Long
    lpfnWndProc As Long
    cbClsExtra As Long
    cbWndExtra As Long
    hInstance As Long
    hIcon As Long
    hCursor As Long
    hbrBackground As Long
    lpszMenuName As String
    lpszClassName As String
    hIconSm As Long
End Type

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Type POINTAPI
    x As Long
    y As Long
End Type

Private Type MSG
    hwnd As Long
    Message As Long
    wParam As Long
    lParam As Long
    time As Long
    pt As POINTAPI
End Type

Private Type BITMAPINFOHEADER '40 bytes
    biSize As Long
    biWidth As Long
    biHeight As Long
    biPlanes As Integer
    biBitCount As Integer
    biCompression As Long
    biSizeImage As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed As Long
    biClrImportant As Long
End Type

Private Type BITMAPFILEHEADER
    bfType As Integer
    bfSize As Long
    bfReserved1 As Integer
    bfReserved2 As Integer
    bfOhFileBits As Long
End Type

'Declaret
Private Declare Function RegisterClassEx Lib "user32.dll" Alias "RegisterClassExA" (ByRef pcWndClassEx As WNDCLASSEX) As Integer
Private Declare Function UnregisterClass Lib "user32.dll" Alias "UnregisterClassA" (ByVal lpClassName As String, ByVal hInstance As Long) As Long

Private Declare Function CreateWindowEx Lib "user32.dll" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, ByRef lpParam As Any) As Long
Private Declare Function DestroyWindow Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function DefWindowProc Lib "user32.dll" Alias "DefWindowProcA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function MoveWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
Private Declare Function SetLayeredWindowAttributes Lib "user32.dll" (ByVal hwnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
Private Declare Function GetForegroundWindow Lib "user32.dll" () As Long
Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As Long, ByRef lpRect As RECT) As Long

Private Declare Function GetMessage Lib "user32.dll" Alias "GetMessageA" (ByRef lpMsg As MSG, ByVal hwnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long) As Long
Private Declare Function TranslateMessage Lib "user32.dll" (ByRef lpMsg As MSG) As Long
Private Declare Function DispatchMessage Lib "user32.dll" Alias "DispatchMessageA" (ByRef lpMsg As MSG) As Long

Private Declare Function LoadImage Lib "user32.dll" Alias "LoadImageA" (ByVal hInst As Long, ByVal lpsz As String, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function GetWindowDC Lib "user32.dll" (ByVal hwnd As Long) As Long

Private Declare Function BitBlt Lib "gdi32.dll" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

Private Declare Function SetTimer Lib "user32.dll" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32.dll" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long

Private Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vKey As Long) As Integer
Private Declare Function GetCursorPos Lib "user32.dll" (ByRef lpPoint As POINTAPI) As Long

'Muuttujat
Dim BitmapWidth As Long         'Bittikartan leveys
Dim BitmapHeight As Long        'Bittikartan korkeus
Dim BitmapFile As String        'Bittikartan tiedostonimi (& polku)
Dim MascotWindowHandle As Long  'Kahva luotuun ikkunaan
Dim MascotWindowDC As Long      'Ikkunan device context
Dim BitmapHandle As Long        'Kahva bittikarttaan
Dim MemoryDC As Long            'Device context bittikartalle
Dim WindowLocation As RECT      'Aktiivisen ikkunan sijainti

Private Sub Main()
    Dim Message As MSG
    Dim FileHeader As BITMAPFILEHEADER
    Dim InfoHeader As BITMAPINFOHEADER

    'Asetetaan bittikartan polku
    BitmapFile = App.Path & "\suzuna.bmp"

    'Luetaan bittikartan headerit, joista saadaan selville sen koko
    Open BitmapFile For Binary Access Read As #1
    Get #1, , FileHeader
    Get #1, , InfoHeader
    Close #1

    BitmapWidth = InfoHeader.biWidth
    BitmapHeight = InfoHeader.biHeight

    'Yritetään rekisteröidä ikkunan luokka
    If Not RegisterWindowClass Then
        MsgBox "Failed to register window class", vbCritical
        Terminate
    End If

    'Yritetään luoda ikkuna
    If Not CreateMascotWindow Then
        MsgBox "Failed to create the window", vbCritical
        Terminate
    End If

    'Tehdään magentasta (255, 0, 255) läpinäkyvä väri
    Call SetLayeredWindowAttributes(MascotWindowHandle, RGB(255, 0, 255), 255&, LWA_COLORKEY)

    'Otetaan selville vastaluodun ikkunan device context
    MascotWindowDC = GetWindowDC(MascotWindowHandle)

    'Yritetään ladata bittikartta
    If Not LoadBitmap Then
        MsgBox "Failed to load " & BitmapFile, vbCritical
        Terminate
    End If

    'Luodaan muistiin device context, johon bittikartta voidaan valita
    MemoryDC = CreateCompatibleDC(ByVal 0&)

    If SelectObject(MemoryDC, BitmapHandle) = 0 Then
        MsgBox "Failed to select bitmap to memory DC", vbCritical
        Terminate
    End If

    'Luodaan ajastin
    Call SetTimer(MascotWindowHandle, 1&, 75&, AddressOf TimerProc)

    'Message looppi pyörii niin kauan, kuin aiemmin luotu ikkuna on olemassa (=koko ohjelman päälläolon ajan)
    Do While 0 <> GetMessage(Message, 0&, 0&, 0&)
        Call TranslateMessage(Message)
        Call DispatchMessage(Message)
        DoEvents
    Loop

    End
End Sub

'Tuhoaa kaikken muistissa olevan tavaran ja sulkee ohjelman
Private Sub Terminate()
    'Tuhotaan muistissa oleva DC
    Call DeleteDC(MemoryDC)

    'Tuhotaan bittikartta
    Call DeleteObject(BitmapHandle)

    'Tuhotaan ajastin
    Call KillTimer(MascotWindowHandle, 1&)

    'Tuhotaan ikkuna
    Call DestroyWindow(MascotWindowHandle)

    'Poistetaan ikkunaluokan rekisteröinti
    Call UnregisterClass("mascotwindow", App.hInstance)

    'Lopetetaan ohjelma
    End
End Sub

'Rekisteröi luokan "mascotwindow"
Private Function RegisterWindowClass() As Boolean
    Dim ClsDescriptor As WNDCLASSEX

    'Täytetään structi
    With ClsDescriptor
        .cbSize = Len(ClsDescriptor)
        .style = CS_HREDRAW + CS_VREDRAW
        .hInstance = App.hInstance
        'VB ei hyväksy tähän suoraan tuota AddressOfia, vaan se pitää kierrättää funktion kautta
        .lpfnWndProc = ReturnParam(AddressOf WindowProc)
        .lpszClassName = "mascotwindow"
    End With

    'Suoritetaan rekisteröinti ja palautetaan true tai false
    RegisterWindowClass = (RegisterClassEx(ClsDescriptor) <> 0&)
End Function

'Luo ikkunan, jossa "maskotti" näytetään
Private Function CreateMascotWindow() As Boolean
    'Luodaan layeroitu, reunaton, otsikkopalkiton, läpinäkyvä ikkuna luokkaa "mascotwindow"
    'Kooksi laitetaan bittikartan koko ja ikkuna asetetaan piiloon ruudun ulkopuolelle
    MascotWindowHandle = CreateWindowEx(WS_EX_LAYERED Or WS_EX_TOOLWINDOW Or WS_EX_TOPMOST Or WS_EX_TRANSPARENT, "mascotwindow", "Mascot", WS_VISIBLE Or WS_POPUP, -BitmapWidth, -BitmapHeight, BitmapWidth, BitmapHeight, 0&, 0&, App.hInstance, ByVal 0&)
    'Palautetaan true tai false
    CreateMascotWindow = (MascotWindowHandle <> 0&)
End Function

'Lataa bittikartan muistiin
Private Function LoadBitmap() As Boolean
    BitmapHandle = LoadImage(ByVal 0&, BitmapFile, IMAGE_BITMAP, BitmapWidth, BitmapHeight, LR_LOADFROMFILE)
    LoadBitmap = (BitmapHandle <> 0&)
End Function

'Palauttaa parametriksi annetun arvon. Käytetään ohittamaan VB:n bugi (ks. yllä)
Private Function ReturnParam(Param As Long) As Long
    ReturnParam = Param
End Function

'WindowProc -callback funktio
'Windows kutsuu tätä aina, kun ikkunallemme tapahtuu jotain oleellista
Public Function WindowProc(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    'Otetaan selvää, minkä viestin Windows lähetti
    Select Case wMsg
        Case WM_PAINT
            'WM_PAINT käskee ikkunaa (uudelleen)piirtämään itsensä, joten teemme työtä käskettyä ja piirrämme bittikartan ikkunaan
            Call BitBlt(MascotWindowDC, 0&, 0&, BitmapWidth, BitmapHeight, MemoryDC, 0&, 0&, vbSrcCopy)
    End Select
    'Jotta kaikkia viestejä ei tarvitse itse käsitellä, ohjaamme käsittelyn oletusikkunaproseduurille
    WindowProc = DefWindowProc(ByVal hwnd, ByVal wMsg, ByVal wParam, ByVal lParam)
End Function

'TimerProc callback-funktio
'Sub Mainissa luomamme ajastin kutsuu tätä 75 millisekunnin välein
Public Function TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTime As Long) As Long
    Dim CursorLocation As POINTAPI

    'Katsotaan, onko hiiren oikeaa nappia painettu viime kerran jälkeen
    If GetAsyncKeyState(vbKeyRButton) <> 0& Then
        'Jos on, niin katsomme, onko kursori ikkunamme kohdalla, ja mikäli näin on, kysymme, haluaako käyttäjä lopettaa ohjelman
        Call GetCursorPos(CursorLocation)
        If CursorLocation.x > WindowLocation.Left + CLng(0.9 * (WindowLocation.Right - WindowLocation.Left - BitmapWidth)) _
        And CursorLocation.x < WindowLocation.Left + CLng(0.9 * (WindowLocation.Right - WindowLocation.Left - BitmapWidth)) + BitmapWidth _
        And CursorLocation.y > WindowLocation.Top - BitmapHeight _
        And CursorLocation.y < WindowLocation.Top Then
            If MsgBox("Wanna quit?", vbQuestion + vbYesNo) = vbYes Then Terminate
        End If
    End If

    'Otetaan selville aktiivisen ikkunan paikka
    Call GetWindowRect(GetForegroundWindow, WindowLocation)
    'Siirretään maskotti-ikkunamme istumaan tuon aktiivisen ikkunan päälle
    Call MoveWindow(MascotWindowHandle, WindowLocation.Left + CLng(0.9 * (WindowLocation.Right - WindowLocation.Left - BitmapWidth)), WindowLocation.Top - BitmapHeight, BitmapWidth, BitmapHeight, True)
End Function

Vilikki [14.07.2004 01:12:27]

#

Ovela on, heti hurahti wario maskotiksi :)

Meitzi [14.07.2004 17:49:17]

#

Ihan toimiva.

Toki aika tärkeä olisi tarkistaa että ohjelmia ei ole päällä kuin yksi kerrallaan. Itselläni kun ei sattunut olemaan ensin yhtään ikkunaa auki ja sitten painelin sitä exeä että nooh eikös se aukea. Olisi myös ihan kätevä jos ohjelman saisi jollain muullakin sammutettu kuin pakottamallla.

Blaze [14.07.2004 17:56:41]

#

lainaus:

Toki aika tärkeä olisi tarkistaa että ohjelmia ei ole päällä kuin yksi kerrallaan.

Tuo olis muuten pätevä ominaisuus. Vois lisätä. Ellen nyt ihan väärin muista, niin täällä taisi olla tuohon oikein vinkkikin.

lainaus:

jos ohjelman saisi jollain muullakin sammutettu kuin pakottamallla.

Hiiren kakkosnappia siinä sen kuvan päällä. Kun jaksais, niin kehittelis jotain dokumentaatiota :)

AdeRide [15.07.2004 02:25:34]

#

Oon nähnyt sellaisia lammas -maskotteja, jotka kävelee ja syö ruohoo jne. ja sitten kun ottaa ikkunan pois alta niin se tippuu alapalkin tai toisen ikkunan päälle jne. ja se ei oo vain kiinnityksissä siihen yhteen ikkunaan.

Sellaisen kun väännät niin WAUUUUU!!!

Tuo oli hieman tylsä, mutta ihan OK.

PeQ [15.07.2004 13:03:40]

#

tässä on linkki aderiden kertomaan lampaaseeen : http://website.lineone.net/~terrirob/games/esheep.zip

noita on kiva pistää monta ja kattoo ku ne riehuu... :)

BlueByte [18.07.2004 16:00:00]

#

onko love hina jotain hentaita

BlueByte [18.07.2004 23:27:27]

#

taitaa olla, latasin jonkun pätkän dc++lla heh

Mestre [19.07.2004 21:14:34]

#

lainaus:

onko love hina jotain hentaita

Nimi ainakin kuulostaa vähän...

Aika turha ja rasittava juttu toi maskotti.

juhaz [21.07.2004 01:09:46]

#

BlueByte, ei ole hentaita vaan animea... animen ja hentain ero on se, että hentai on k18 jos ymmärrät ;)

Ainakaan katsomani jaksot love hinasta eivät sitä sisältäneet.

miiro [21.09.2004 11:14:03]

#

mist sait ton esheepin se on tietääkseni sharevaree vai muistanko väärin

miiro [21.09.2004 11:14:30]

#

mist sait ton esheepin se on tietääkseni sharevaree vai muistanko väärin

miiro [21.09.2004 11:53:47]

#

eSheep toimii <win2000 ssakin joten voisiko joku tehdä sellaisen jutun? (siis joka toimisi myös susikasissa)

Blaze [21.09.2004 16:14:32]

#

Ainoa, mikä tuossa 2k+:n vaatii on tuo SetLayeredWindowAttributes. Kehitä joku oma systeemi, jolla saat epäsäännöllisiä/läpinäkyviä/kivoja ikkunoita, käytä vaikka SetWindowRgn:ää, ja loppu toimii ihan samalla tavalla.

D4_B34M [18.10.2004 19:05:19]

#

Ihan kiva, luulis kyllä että vähän vähempikin koodi riittäisi mutta ei kai sitten...

VbMan [18.10.2004 21:02:27]

#

Ihan kiva...
Taas yks todiste, että XP on susi... ...Sain XP:n jumiin kun mätin niitä lampaita tarpeeks, ja meni kiintolevy formatointiin...

Fisher [28.12.2004 17:01:22]

#

lainaus:

eSheep toimii <win2000 ssakin joten voisiko joku tehdä sellaisen jutun? (siis joka toimisi myös susikasissa)

toimii xp:ssäkin...

Harrastelija [05.05.2005 09:39:53]

#

Minne toi pitäis niinku kopioida?
Moduuliin, Formiin, ei toimi kyllä mitenkään!

Blaze [05.05.2005 10:42:13]

#

Moduuliin, ja projektin asetuksista Startup Objektiksi "Sub Main".

Valle [24.01.2006 13:42:59]

#

Mulla valittaa:

Failed to load C:/program files/Microsoft Visual Basic/suzuna.bmp

Mitä pitäis tehä ,kun laitoin koodin moduuliin ja määritin startup objektiksi: Sub Main?

moptim [28.08.2006 08:42:36]

#

suhteellisen pitkä
ja valle: tallenna jonnekin ja laita suzuna.bmp samaan kansioon, ei kai sinulla ole Visual Basicin kansiossa mitään bittikarttoja?

AakenStein [16.02.2007 21:26:02]

#

Ihan hauska koodi.
Muuten, jos haluutte jonku toisen kuvan, nii ladatkaa vaa toi mascot.zip ja sit poistakaa suzana.bmp ja laittakaa sinne kuva minkä haluutte ja nimeks suzana :D:D
( vinkki niille jotka ei jaksa koodaa omaa )

gamehouse [27.06.2007 10:09:14]

#

Tämä ei toimi... (win 98), mutta eSheep toimii!

moptim [19.08.2007 10:40:24]

#

gamehouse, voisit varmasti lukea noi jutut mitä alussa selostettiin.

Blaze kirjoitti:

Käyttää layeröityä ikkunaa, joten vaatii Windows 2000:n tai uudemman.

Weggo [21.01.2009 21:00:48]

#

Tais olla aika tylsää ku tommosta väsäsit :) Kuitenkin todella hieno luomus


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta