Page 2 of 3

Posted: Sun Jun 22, 2008 6:06 pm
by netmaestro
Small update:

- Fixed an issue where clicking a lot on the window near the end could have caused an IMA

- Added single-instance enforcement

- Source is released

You'll need the sounds and pictures: https://lloydsplace.com/winapistupid.zip

I got the builder sprites free from here: http://reinerstileset.4players.de/

The program could be made smaller by using gdiplus to tilt the window and using small sprites to update only the dented part of the window, but these are more work and I'm too lazy...

Code: Select all

;========================================================================
; Program:          Resize Window Improvement                           
; Author:           Lloyd Gallant (netmaestro)                                     
; Date:             June 21, 2008                                       
; Target OS:        Windows 2000/XP and later                           
; Target Compiler:  PureBasic 4.0 and later                             
; License:          Free, unrestricted, no warranty                     
; Why:              I just haven't written anything silly in a while    
;========================================================================    

Import "gdiplus.lib"
  GdipCreateBitmapFromStream(*stream, *image) 
  GdipGetImageWidth(*image, *Width) 
  GdipGetImageHeight(*image, *Height) 
  GdipCreateFromHDC( hdc.i, *gfx) 
  GdipDrawImageRectI(*gfx, *image, a.i, b.i, Width.i, Height.i) 
  GdipDeleteGraphics(*gfx)  
  GdipDisposeImage(*image) 
  GdiplusStartup(*token, *input, a.i)
  GdiplusShutdown(*token) 
EndImport

Declare CatchPNG(ImageNumber, Address, Length) 
Declare MainThread(void)
Declare WalkingW(void)
Declare WalkingE(void)
Declare WalkingNE(void)
Declare WalkingSE(void)
Declare HammeringE(void)
Declare HammeringW(effect)
Declare UpdateWindow(window,img)
Declare Instance_Running(LockStr$)

DataSection
  sheet:  
  IncludeBinary "builder2.png" 
  endsheet:
  win1:   
  IncludeBinary "win1.png"     
  endwin1:
  tilt1:  
  IncludeBinary "win2.png"     
  endtilt1:
  tilt2:  
  IncludeBinary "win3.png"     
  endtilt2:
  bent1:  
  IncludeBinary "win4.png"     
  endbent1:
  bent2:  
  IncludeBinary "win5.png"    
  endbent2:
  swear:  
  IncludeBinary "swear.png"    
  endswear:
  giveup: 
  IncludeBinary "giveup.png"   
  endgiveup:
  walk:   
  IncludeBinary "walk.wav"
  hammer: 
  IncludeBinary "hammer.wav"
EndDataSection

If Instance_Running("netmaestro's Resize Window Improvement")
  End
EndIf

Global soundon = InitSound()
If soundon
  CatchSound(0, ?hammer)
  CatchSound(1, ?walk)
EndIf

CatchPNG(0, ?sheet,?endsheet-?sheet)
Global win1    = CatchPNG(#PB_Any, ?win1, ?endwin1-?win1)
Global tilt1   = CatchPNG(#PB_Any, ?tilt1, ?endtilt1-?tilt1)
Global tilt2   = CatchPNG(#PB_Any, ?tilt2, ?endtilt2-?tilt2)
Global bent1   = CatchPNG(#PB_Any, ?bent1, ?endbent1-?bent1)
Global bent2   = CatchPNG(#PB_Any, ?bent2, ?endbent2-?bent2)
Global swear   = CatchPNG(#PB_Any, ?swear, ?endswear-?swear)
Global giveup  = CatchPNG(#PB_Any, ?giveup, ?endgiveup-?giveup)
Global wait    = GrabImage(0,#PB_Any, 16*96,192,96,96)
Global threadfinished=0


Global NewList walke()
For i=0 To 7
  AddElement(walke())
  walke()=GrabImage(0,#PB_Any, 96*i,0,96,96)
Next
FirstElement(walke())

Global NewList walkw()
For i=0 To 7
  AddElement(walkw())
  walkw()=GrabImage(0, #PB_Any, i*96,96,96,96)
Next
FirstElement(walkw())

Global NewList walkne()
For i=0 To 7
  AddElement(walkne())
  walkne()=GrabImage(0,#PB_Any, i*96,192,96,96)
Next
FirstElement(walkne())

Global NewList hammere()
For i=0 To 10
  AddElement(hammere())
  hammere()=GrabImage(0, #PB_Any, (96*8)+i*96,0,96,96)
Next
FirstElement(hammere())

Global NewList hammerw()
For i=0 To 10
  AddElement(hammerw())
  hammerw()=GrabImage(0, #PB_Any, (96*8)+i*96,96,96,96)
Next
FirstElement(hammerw())

Global NewList walkse()
For i=0 To 7
  AddElement(walkse())
  walkse()=GrabImage(0,#PB_Any, (96*8)+i*96,192,96,96)
Next
FirstElement(walkse())

win=OpenWindow(0,0,0,320,290,"ResizeWindow Improvement",#PB_Window_BorderLess|#PB_Window_Invisible|#PB_Window_ScreenCentered)
SetWindowLong_(win,#GWL_EXSTYLE, GetWindowLong_(win,#GWL_EXSTYLE)|#WS_EX_LAYERED|#WS_EX_TOOLWINDOW)
UpdateWindow(0, win1)
StickyWindow(0,1)

win2=OpenWindow(1,0,0,320,290,"",#PB_Window_BorderLess|#PB_Window_Invisible, WindowID(0))
SetWindowLong_(win2,#GWL_EXSTYLE, GetWindowLong_(win2,#GWL_EXSTYLE)|#WS_EX_LAYERED|#WS_EX_TOOLWINDOW)
UpdateWindow(1, swear)
StickyWindow(1,1)

HideWindow(0,0)

man = OpenWindow(9,0,0,96,96,"",#PB_Window_BorderLess|#PB_Window_Invisible|#PB_Window_ScreenCentered, WindowID(0))
SetWindowLong_(man,#GWL_EXSTYLE, GetWindowLong_(man,#GWL_EXSTYLE)|#WS_EX_LAYERED|#WS_EX_TOOLWINDOW)
StickyWindow(9,1)
UpdateWindow(9,wait)

main_tid = CreateThread(@MainThread(),0)

Repeat
  WaitWindowEvent(10)
Until GetAsyncKeyState_(#VK_ESCAPE) & 32768 
End

Procedure MainThread(void)
  Protected tid
  
  ; Opening view
  Delay(1000)
  HideWindow(9,0)
  Delay(1000)
  
  ; Walk to top right corner
  tid=CreateThread(@WalkingNE(),0)
  Repeat
    Delay(1)
  Until WindowX(9)>=WindowX(0)+WindowWidth(0)-20
  threadfinished = #True:WaitThread(tid)
  
  ; Hammer on right corner 
  tid=CreateThread(@HammeringW(),0)
  WaitThread(tid)
  Delay(500)
  ResizeWindow(1, WindowX(9)+10,WindowY(9)-80,#PB_Ignore,#PB_Ignore)
  HideWindow(1,0):Delay(2000):HideWindow(1,1)
  
  ; Walk to top left corner
  tid=CreateThread(@WalkingW(),0)
  Repeat
    Delay(1)
  Until WindowX(9)<=WindowX(0)-110
  threadfinished = #True:WaitThread(tid)
  tid=CreateThread(@WalkingSE(),0)
  Repeat
    Delay(1)
  Until WindowX(9)>=WindowX(0)-80
  threadfinished = #True:WaitThread(tid)  
  
  ; Hammer on left corner
  tid=CreateThread(@HammeringE(),0)
  WaitThread(tid)
  
  ; Walk to right of mid-window
  tid=CreateThread(@WalkingSE(),0)
  Repeat
    Delay(1)
  Until WindowX(9)>=WindowX(0)+20
  threadfinished = #True:WaitThread(tid)  
  tid=CreateThread(@WalkingE(),0)
  Repeat
    Delay(1)
  Until WindowX(9)>=WindowX(0)+WindowWidth(0)-20
  threadfinished = #True:WaitThread(tid)  
  
  ; Hammer on mid-window
  tid=CreateThread(@HammeringW(),1) ; parameter specifies effect of hammering: 0=tilt,1=dent
  WaitThread(tid)
  Delay(500)
  ResizeWindow(1, WindowX(9)+10,WindowY(9)-80,#PB_Ignore,#PB_Ignore)
  HideWindow(1,0):Delay(2000):HideWindow(1,1)   
  
  ; Walk back to mid window and give up
  tid=CreateThread(@WalkingW(),0)
  Repeat
    Delay(1)
  Until WindowX(9)<=WindowX(0)+110
  threadfinished = #True:WaitThread(tid)
  UpdateWindow(9, wait)
  Delay(1000)
  UpdateWindow(1, giveup)
  ResizeWindow(1, WindowX(9),WindowY(9)-110,#PB_Ignore,#PB_Ignore)
  HideWindow(1,0):Delay(3000):HideWindow(1,1)   
  
  ; End the program
  PostMessage_(WindowID(0), #WM_SYSCOMMAND, #SC_CLOSE,0) 
  
EndProcedure

Procedure HammeringW(effect)
  Protected hits = 0 ; Counts the hits
  Protected cc   = 0 ; Counts the sprite frames, record a hit on 7th frame
  
  Repeat
    UpdateWindow(9, hammerw())
    If cc=7 
      If soundon
        PlaySound(0)
      EndIf
      hits+1
    EndIf
    Delay(100)
    If Not NextElement(hammerw())
      FirstElement(hammerw())
      cc=0
    Else
      cc+1  
    EndIf
    Select effect
      Case 0
        If hits = 2 
          UpdateWindow(0, tilt1)
        EndIf
        If hits = 4 
          UpdateWindow(0,tilt2)
        EndIf
      Case 1
        If hits = 2 
          UpdateWindow(0,bent1)
          ResizeWindow(9,WindowX(9)-1,#PB_Ignore,#PB_Ignore,#PB_Ignore)
        EndIf
        If hits = 4 
          UpdateWindow(0,bent2)
        EndIf
    EndSelect      
  Until hits = 4 And cc=0
EndProcedure

Procedure HammeringE(void)
  Protected hits = 0 ; Counts the hits
  Protected cc   = 0 ; Counts the sprite frames, record a hit on 7th frame
  
  Repeat
    UpdateWindow(9, hammere())
    If cc=7 
      If soundon
        PlaySound(0)
      EndIf
      hits+1
    EndIf
    Delay(100)
    If Not NextElement(hammere())
      FirstElement(hammere())
      cc=0
    Else
      cc+1  
    EndIf
    If hits = 2 
      UpdateWindow(0,tilt1)
    EndIf
    If hits = 4 
      UpdateWindow(0,win1)
    EndIf
    
  Until hits = 4 And cc=0
EndProcedure

Procedure WalkingW(void)
  threadfinished=0
  Repeat
    UpdateWindow(9,walkw())
    If (cc=1 Or cc=5) And soundon
      PlaySound(1)
    EndIf
    ResizeWindow(9, WindowX(9)-5,#PB_Ignore,#PB_Ignore,#PB_Ignore)
    Delay(100)
    If Not NextElement(walkw())
      FirstElement(walkw())
      cc=0
    Else
      cc+1  
    EndIf
  Until threadfinished
EndProcedure

Procedure WalkingE(void)
  threadfinished=0
  Repeat
    UpdateWindow(9,walke())
    If (cc=1 Or cc=5) And soundon
      PlaySound(1)
    EndIf
    ResizeWindow(9, WindowX(9)+5,#PB_Ignore,#PB_Ignore,#PB_Ignore)
    Delay(100)
    If Not NextElement(walke())
      FirstElement(walke())
      cc=0
    Else
      cc+1  
    EndIf
  Until threadfinished
EndProcedure

Procedure WalkingNE(void)
  threadfinished=0
  Repeat
    UpdateWindow(9,walkne())
    If (cc=1 Or cc=5) And soundon
      PlaySound(1)
    EndIf
    ResizeWindow(9, WindowX(9)+5,WindowY(9)-3,#PB_Ignore,#PB_Ignore)
    Delay(100)
    If Not NextElement(walkne())
      FirstElement(walkne())
      cc=0
    Else
      cc+1  
    EndIf
  Until threadfinished
EndProcedure

Procedure WalkingSE(void)
  threadfinished=0
  Repeat
    UpdateWindow(9,walkse())
    If (cc=1 Or cc=5) And soundon
      PlaySound(1)
    EndIf
    ResizeWindow(9, WindowX(9)+5,WindowY(9)+5,#PB_Ignore,#PB_Ignore)
    Delay(100)
    If Not NextElement(walkse())
      cc=0
      FirstElement(walkse())
    Else
      cc+1
    EndIf
  Until threadfinished
EndProcedure

Procedure UpdateWindow(window,img)
  hDC = StartDrawing(ImageOutput(img)) 
    sz.SIZE 
    sz\cx = ImageWidth(img) 
    sz\cy = ImageHeight(img) 
    ContextOffset.POINT 
    BlendMode.BLENDFUNCTION 
    BlendMode\SourceConstantAlpha = 255 
    BlendMode\AlphaFormat = 1 
    UpdateLayeredWindow_(WindowID(window), 0, 0, @sz, hDC, @ContextOffset, 0, @BlendMode, 2) 
  StopDrawing()
EndProcedure

Procedure CatchPNG(ImageNumber, Address, Length) 
  
  CompilerIf Defined(GdiplusStartupInput, #PB_Structure) = 0 
    Structure GdiplusStartupInput 
      GdiPlusVersion.l 
      *DebugEventCallback.Debug_Event 
      SuppressBackgroundThread.l 
      SuppressExternalCodecs.l 
    EndStructure 
  CompilerEndIf  
  
  Structure StreamObject 
    block.l 
    *bits 
    stream.ISTREAM 
  EndStructure 
  
  Protected lib 
  lib = OpenLibrary(#PB_Any, "gdiplus.dll") 
  If Not lib 
    ProcedureReturn -1 
  EndIf 
  
  input.GdiplusStartupInput 
  input\GdiPlusVersion = 1 
  
  GdiplusStartup( @*token, @input, #Null) 
  If *token 
    stream.streamobject 
    Stream\block = GlobalAlloc_(#GHND, Length) 
    Stream\bits = GlobalLock_(Stream\block) 
    CopyMemory(address, stream\bits, Length) 
    If CreateStreamOnHGlobal_(stream\bits, 0, @Stream\stream) = #S_OK 
      CallFunction(lib, "GdipCreateBitmapFromStream", Stream\stream , @*image) 
      Stream\stream\Release() 
      GlobalUnlock_(Stream\bits) 
      GlobalFree_(Stream\block) 
    Else 
      GdiplusShutdown(*token) 
      ProcedureReturn 0 
    EndIf 
    
    If *image 
      GdipGetImageWidth(*image, @Width.l) 
      GdipGetImageHeight(*image, @Height.l) 
      If imagenumber = #PB_Any 
        return_imagenumber = CreateImage(#PB_Any, Width, Height, 32, #PB_Image_Transparent) 
      Else 
        CreateImage(return_imagenumber, Width, Height, 32, #PB_Image_Transparent) 
      EndIf 
      hDC = StartDrawing(ImageOutput(return_imagenumber)) 
        GdipCreateFromHDC(hdc, @*gfx) 
        GdipDrawImageRectI(*gfx, *image, 0, 0, Width, Height) 
      StopDrawing()  
      GdipDeleteGraphics(*gfx)  
      GdipDisposeImage(*image) 
      GdiplusShutdown(*token) 
      
      ProcedureReturn return_imagenumber 
    Else 
      ProcedureReturn -1 
    EndIf 
  Else 
    ProcedureReturn -1 
  EndIf 
EndProcedure 

Procedure Instance_Running(LockStr$)
  *MyMutex = CreateMutex_(#Null, 1, LockStr$)
  If *MyMutex <> 0 And GetLastError_() = #ERROR_ALREADY_EXISTS
    CloseHandle_(*MyMutex)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Posted: Sun Jun 22, 2008 6:49 pm
by byo
Wow, well done. :lol:

Posted: Mon Jun 23, 2008 11:49 am
by Kwai chang caine
I don't know if it's the fault of the PC of my job, but i have tried to run your code and your exe on it and i have some problem :cry:

This macine works on W2000 SP4, is it normal ???

Posted: Mon Jun 23, 2008 12:08 pm
by netmaestro
The code uses gdiplus to load the png images, and I believe gdiplus doesn't ship with w2000. But gdiplus.dll is a free download from Microsoft, so you could DL it and put it in \system32 and see if it works now.

Posted: Mon Jun 23, 2008 12:48 pm
by Kwai chang caine
Thanks a lot, NETMAESTRO
I go to do all that you said to me 8)

I wish you a good day :D

Posted: Mon Jun 23, 2008 12:53 pm
by Kwai chang caine
Yes, you are always right :D

I put the gdiplus.dll in the same directory of the application, and your splendid code works fine now

Thanks again 8)

Posted: Mon Jun 23, 2008 1:00 pm
by netmaestro
Very good but it should go in \windows\system32 so other applications that might use it can find it too.

Posted: Mon Jun 23, 2008 2:12 pm
by Kwai chang caine
Yes especially the DLL is big 1.6 Mo.
It's more better to put it in system32 for not instal in every application :wink:

I love your little worker :D

I search all a day somes picture with green background or other, but it's very difficult to find :?
I find with the "pre-keyed" word in google or "greenscreen" but they are not full of result.

A society sell severals animation and movie, but it's very expensive :?
http://www.timelinegfx.com/freegreenscreen.html

A solution, ask to my wife, to dance in front of a green cloth :lol:

I continue my search.....

Posted: Mon Jun 23, 2008 3:58 pm
by Rook Zimbabwe
Well... stupid is a mean word! I mean it just does what it is told to do!!! If it is told stupid, then it does stupid! (Look at all my programs for an example of someone telling the computer stupid! ) :wink:

Posted: Mon Jun 23, 2008 5:34 pm
by Psychophanta
@netmaestro, nice one! 8)
Thanks for the source.

I have been near to complain because reading the title "Resize Window Improvement", i have been trying to manually resize the window and it didn't work! :lol:

Posted: Mon Jun 23, 2008 11:03 pm
by Ollivier
Threads managing is perfect (XP . 1GHz . 1GB)
Graphism is good too.

API is less stupid with men like you.

Thank you

Posted: Thu Jun 26, 2008 7:56 am
by idle
that made my day!

:D

Posted: Thu Jun 26, 2008 6:27 pm
by npath
Hilarious... I really enjoyed your new implementation of resizing windows.

Re: Windows API is stupid!

Posted: Tue Dec 27, 2016 8:21 am
by netmaestro
I really enjoyed this one and I was disappointed when I lost the files for it last year. But I did post the code and so now that I have some spare time I've created new graphics and sounds for it and it's back up and running again, all links working.