Nifty Fancy Window Code [Windows]

Share your advanced PureBasic knowledge/code with the community.
JustinJack
User
User
Posts: 89
Joined: Thu Feb 04, 2010 7:34 am
Location: Decatur, TX
Contact:

Nifty Fancy Window Code [Windows]

Post by JustinJack »

I coded this to do exactly what I wanted it to. You can change it to however you'd like it. I have lots of ideas, but I just got this done and decided to post it because I don't know *WHEN* I'll get around to finishing it up enough to be called a "Library". But, it's very cool and very useful for little screen pops, or even pop up windows that a user needs to select something from. I have it set to go away if the mouse moves out of the window RECT, so that it doesn't interfere with work flow it you just need it to pop up a quick bit of info.

Code: Select all

;- Jelly Window Library
;- by Justin Jack
;- Use as you please



Structure MOVE_TO
  x.i
  y.i
  cx.i
  cy.i
  cxAdjust.i
  bounceback.i
  iNumSteps.i
  iStepCounter.i
  iRemainder.i
  bIsAnimating.b
  changePerScoop.i
  cAlpha.i
EndStructure

Structure JELLY_CONTROL_SET
  iMouseInTimer.i
  bMouseIn.b
  moveto.MOVE_TO
EndStructure

Enumeration
  #MOUSE_TIMER = 763
  #ANIMATION_SHOW
EndEnumeration



Structure JELLY_WINDOW_INFO
  hDcWnd.i
  iJellyColor.i
  iWindowBMP.i
  hOldDcWnd.i
  hOldBMP.i
  numWindow.i
  hRgn.i
  *lpOldWndProc
  control.JELLY_CONTROL_SET
EndStructure


Procedure Make_Jelly_Images_Window( w_Window )
  
  If Not(IsWindow(w_Window))
    If Not(IsWindow_(w_Window))
      ProcedureReturn #False
    Else
      hWnd = w_Window
    EndIf
  Else
    hWnd = WindowID(w_Window)
  EndIf
  *lpjiw.JELLY_WINDOW_INFO = GetWindowLongPtr_(hWnd, #GWLP_USERDATA)
  oldRgn = *lpjiw\hRgn
  
  
  btn_size.SIZE\cx = WindowWidth(*lpjiw\numWindow)
  btn_size\cy      = WindowHeight(*lpjiw\numWindow)
  jelly_color = *lpjiw\iJellyColor
  oldImage = *lpjiw\iWindowBMP
  If btn_size\cx <= 0 
    btn_size\cx = 1
  EndIf
  *lpjiw\iWindowBMP = CreateImage(#PB_Any, btn_size\cx, btn_size\cy, 24)
  StartDrawing(ImageOutput(*lpjiw\iWindowBMP))
  Box(0, 0, btn_size\cx, btn_size\cy, jelly_color)
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  RoundBox(0, 0, btn_size\cx, btn_size\cy, 20, 20, jelly_color)
  DrawingMode(#PB_2DDrawing_Gradient|#PB_2DDrawing_AlphaBlend)
  BackColor(RGBA(0, 0, 0, 130))
  FrontColor(RGBA(0, 0, 0, 00))
  LinearGradient(-10, 0, (btn_size\cx / 3), 0)
  RoundBox(0, 0, btn_size\cx, btn_size\cy, 4, 4)
  FrontColor(RGBA(0, 0, 0, 130))
  BackColor(RGBA(0, 0, 0, 00))
  LinearGradient(btn_size\cx - (btn_size\cx / 3), 0, (btn_size\cx + 10), 0)
  RoundBox(0, 0, btn_size\cx, btn_size\cy, 4, 4)
  FrontColor(RGBA($FF, $FF, $FF, 00))
  BackColor(RGBA($FF, $FF, $FF, 150))
  LinearGradient(0, 0, 0, (btn_size\cy / 3) * 2)
  RoundBox(0, 0, btn_size\cx, btn_size\cy, 4, 4)
  ;DrawingMode(#PB_2DDrawing_Outlined)
  ;rr = 12
  ;RoundBox(0, 0, btn_size\cx - 1, btn_size\cy - 1,rr, rr, #Black)
  StopDrawing()
  
  *lpjiw\hRgn = CreateRoundRectRgn_(0, 0, WindowWidth(*lpjiw\numWindow), WindowHeight(*lpjiw\numWindow), 20, 20)
  SetWindowRgn_(hWnd, *lpjiw\hRgn, 0)
  SelectObject_(*lpjiw\hDcWnd, ImageID(*lpjiw\iWindowBMP))
  DeleteObject_(oldRgn)
  
  
  If IsImage(oldImage)
    FreeImage(oldImage)
  EndIf
  
  
EndProcedure


Procedure enFunc( hWnd, hDc )
  Static ControlDC, OrigBmp, iCurrentBMP
  If ControlDC = 0
    hDcx = GetDC_(#Null)
    ControlDC = CreateCompatibleDC_(hDcX)
    iCurrentBMP = CreateCompatibleBitmap_(hDcx, 100, 100)
    OrigBmp = SelectObject_(ControlDC, iCurrentBMP)
    ReleaseDC_(#Null, hDcx)
  EndIf
  If hWnd <> 0
    snName.s = Space(100)
    GetClassName_(hWnd, @snName, 100)
    If snName <> "SysHeader32"
      GetWindowRect_(hWnd, @clrc.rect)
      gp.POINT\x = clrc\left
      gp\y = clrc\top
      ScreenToClient_(GetParent_(hWnd), @gp)
      xDiff = clrc\right - clrc\left
      ydiff = clrc\bottom- clrc\top
      clrc\left = gp\x
      clrc\top = gp\y
      clrc\right = gp\x + xDiff
      clrc\bottom = gp\y + ydiff
      iCurrentBMP = CreateCompatibleBitmap_(ControlDC, clrc\right - clrc\left, clrc\bottom - clrc\top)
      DeleteObject_(SelectObject_(ControlDC, iCurrentBMP))
      SendMessage_(hWnd, #WM_PRINT, ControlDC, #PRF_CLIENT|#PRF_NONCLIENT|#PRF_CHILDREN)
      BitBlt_(hDc, clrc\left, clrc\top, clrc\right - clrc\left, clrc\bottom - clrc\top, ControlDC, 0, 0, #SRCCOPY)
    EndIf
  EndIf
  
  ProcedureReturn hWnd
EndProcedure


Procedure jelly_window_wndproc( hWnd, uMsg, wParam, lParam )
  *lpJwInfo.JELLY_WINDOW_INFO = GetWindowLongPtr_(hWnd, #GWLP_USERDATA)
  If *lpJwInfo = 0
    ProcedureReturn 0
  EndIf
  Select uMsg
    Case #WM_TIMER
      Select wParam
        Case #MOUSE_TIMER
          GetCursorPos_(@mt.POINT)
          inRect = #False
          If mt\x >= WindowX(*lpJwInfo\numWindow) And mt\x <= WindowX(*lpJwInfo\numWindow) + WindowWidth(*lpJwInfo\numWindow)
            If mt\y >= WindowY(*lpJwInfo\numWindow) And mt\y <= (WindowY(*lpJwInfo\numWindow) + WindowHeight(*lpJwInfo\numWindow))
              inRect = #True
            EndIf
          EndIf
          If inRect = #False
            SendMessage_(hWnd, #WM_CLOSE, 0, 0)
          EndIf
        Case #ANIMATION_SHOW
          If *lpJwInfo\control\moveto\iStepCounter <= *lpJwInfo\control\moveto\iNumSteps
            cX = WindowX(*lpJwInfo\numWindow)
            cCx = *lpJwInfo\control\moveto\cx
            cX = cX - 100
            *lpJwInfo\control\moveto\iStepCounter + 1
            SetLayeredWindowAttributes_(hWnd, #Null, *lpJwInfo\control\moveto\cAlpha, #LWA_ALPHA)
            *lpJwInfo\control\moveto\cAlpha + *lpJwInfo\control\moveto\changePerScoop
            If *lpJwInfo\control\moveto\iStepCounter = *lpJwInfo\control\moveto\iNumSteps
              *lpJwInfo\control\moveto\cAlpha = 255
              SetLayeredWindowAttributes_(hWnd, #Null, 255, #LWA_ALPHA)
              KillTimer_(hWnd, #ANIMATION_SHOW)
              SetTimer_(hWnd, #ANIMATION_SHOW, 20, #Null)
            EndIf
            SetWindowPos_(hWnd, #Null, cX, *lpJwInfo\control\moveto\y, cCx, *lpJwInfo\control\moveto\cy, #SWP_NOZORDER|#SWP_SHOWWINDOW|#SWP_NOSENDCHANGING|#SWP_NOREDRAW|#SWP_NOACTIVATE)
            If *lpJwInfo\control\moveto\iStepCounter = 2
              Make_Jelly_Images_Window(*lpJwInfo\numWindow)
              hDc = GetDC_(hWnd)
              BitBlt_(hdc, 0, 0, cCx, *lpJwInfo\control\moveto\cy, *lpJwInfo\hDcWnd, 0, 0, #SRCCOPY)
              ReleaseDC_(hWnd, hdc)
              InvalidateRect_(hWnd, 0, 1)
            EndIf
            justMoved = #True
          Else
            cX = WindowX(*lpJwInfo\numWindow)
            cCx = *lpJwInfo\control\moveto\cx
            If cX <> *lpJwInfo\control\moveto\x
              If cX < *lpJwInfo\control\moveto\x
                cX = cX + *lpJwInfo\control\moveto\bounceback
              Else
                cX = cX - 1
              EndIf
              cCx = *lpJwInfo\control\moveto\cx
              SetWindowPos_(hWnd, #Null, cX, *lpJwInfo\control\moveto\y, cCx, *lpJwInfo\control\moveto\cy, #SWP_NOZORDER|#SWP_NOSENDCHANGING|#SWP_NOACTIVATE)
            Else
              KillTimer_(hWnd, #ANIMATION_SHOW)
              *lpJwInfo\control\moveto\bIsAnimating = #False
              done = #True
              InvalidateRect_(hWnd, 0, 1)
            EndIf
          EndIf
          If justMoved = #True
            InvalidateRect_(hWnd, 0, 1)
          EndIf
      EndSelect
    Case #WM_DESTROY
      *lpOldWndProc = *lpJwInfo\lpOldWndProc
      SetWindowLongPtr_(hWnd, #GWLP_WNDPROC, *lpOldWndProc)
      ProcedureReturn CallWindowProc_(*lpJwInfo\lpOldWndProc, hWnd, uMsg, wParam, lParam)
    Case #WM_MOUSEMOVE
      If *lpJwInfo\control\moveto\bIsAnimating = #False
        If *lpJwInfo\control\bMouseIn = #False
          *lpJwInfo\control\bMouseIn = #True
          SetTimer_(hWnd, #MOUSE_TIMER, 50, #Null)
        EndIf
      EndIf
    Case #WM_ERASEBKGND
      ProcedureReturn 1
    Case #WM_WINDOWPOSCHANGED
      If *lpJwInfo\control\moveto\bIsAnimating = #False
        *lpwposc.WINDOWPOS = lParam
        If (*lpwposc\flags & #SWP_NOSIZE) = 0
          Make_Jelly_Images_Window( hWnd )
        EndIf
      EndIf
    Case #WM_PAINT
      BeginPaint_(hWnd, @ps.PAINTSTRUCT)
      EnumChildWindows_(hWnd, @enFunc(), *lpJwInfo\hDcWnd)
      BitBlt_(ps\hdc, ps\rcPaint\left, ps\rcPaint\top, ps\rcPaint\right - ps\rcPaint\left, ps\rcPaint\bottom - ps\rcPaint\top, *lpJwInfo\hDcWnd, ps\rcPaint\left, ps\rcPaint\top, #SRCCOPY)
      ;EnumChildWindows_(hWnd, @enFunc(), ps\hdc)
      EndPaint_(hWnd, @ps)
      ProcedureReturn 0
  EndSelect
  
  ProcedureReturn CallWindowProc_(*lpJwInfo\lpOldWndProc, hWnd, uMsg, wParam, lParam)
  
EndProcedure




Procedure Make_Jelly_Window( w_Window, iColor )
  If Not(IsWindow(w_Window))
    ProcedureReturn #False
  EndIf
  hWnd = WindowID(w_Window)
  dwStyle = #WS_POPUP
  dwExStyle = #WS_EX_TOOLWINDOW|#WS_EX_LAYERED
  SetWindowLongPtr_(hWnd, #GWL_STYLE, dwStyle)
  SetWindowLongPtr_(hWnd, #GWL_EXSTYLE, dwExStyle)
  
  *lpjwi.JELLY_WINDOW_INFO = AllocateMemory(SizeOf(JELLY_WINDOW_INFO))
  *lpjwi\iJellyColor = iColor
  *lpjwi\lpOldWndProc = GetWindowLongPtr_(hWnd, #GWLP_WNDPROC)
  *lpjwi\numWindow = w_Window
  hdc = GetDC_(#Null)
  *lpjwi\hDcWnd = CreateCompatibleDC_(hdc)
  ReleaseDC_(#Null, hDc)
  SetWindowLongPtr_(hWnd, #GWLP_USERDATA, *lpjwi)
  SetWindowLongPtr_(hWnd, #GWLP_WNDPROC, @jelly_window_wndproc())
  Make_Jelly_Images_Window(w_Window)
  *lpjwi\hOldBMP = SelectObject_(*lpjwi\hDcWnd, ImageID(*lpjwi\iWindowBMP))
  *lpjwi\hRgn = CreateRoundRectRgn_(0, 0, WindowWidth(w_Window), WindowHeight(w_Window), 20, 20)
  SetWindowRgn_(hWnd, *lpjwi\hRgn, #False)
  
  SetWindowPos_(hWnd, #Null, #Null, #Null, #Null, #Null, #SWP_NOZORDER|#SWP_NOSIZE|#SWP_NOMOVE)
  ProcedureReturn *lpjwi\iWindowBMP
  
EndProcedure

Procedure Show_Jelly_Window( w_Window, x, y, cx, cy )
  If Not(IsWindow(w_Window))
    ProcedureReturn #False
  EndIf
  hWnd = WindowID(w_Window)
  *lpjwi.JELLY_WINDOW_INFO = GetWindowLongPtr_(hWnd, #GWLP_USERDATA)
  *lpjwi\control\moveto\bIsAnimating = #True
  *lpjwi\control\moveto\x = x
  *lpjwi\control\moveto\y = y
  *lpjwi\control\moveto\cx = cx
  *lpjwi\control\moveto\cy = cy
  GetWindowRect_(GetDesktopWindow_(), @rcdt.RECT)
  *lpjwi\control\moveto\iStepCounter = 1
  *lpjwi\control\moveto\iNumSteps = ((rcdt\right - x) / 100) + 1
  *lpjwi\control\moveto\iRemainder = Abs((rcdt\Right - x) - (*lpjwi\control\moveto\iNumSteps * 100))
  *lpjwi\control\moveto\cxAdjust  = (cx / *lpjwi\control\moveto\iNumSteps) 
  *lpjwi\control\moveto\bounceback = *lpjwi\control\moveto\iRemainder / 10
  *lpjwi\control\moveto\changePerScoop = 205 / *lpjwi\control\moveto\iNumSteps
  *lpjwi\control\moveto\cAlpha = 50
  SetWindowPos_(hWnd, #Null, rcdt\right, y, 0, WindowHeight(*lpjwi\numWindow), #SWP_NOZORDER|#SWP_SHOWWINDOW)
  SetLayeredWindowAttributes_(hWnd, #Null, 00, #LWA_ALPHA)
  SetTimer_(hWnd, #ANIMATION_SHOW, 10, #Null)
  
EndProcedure


Procedure Create_Jelly_Window( cx, cy, iColor )
  mWindow = OpenWindow(#PB_Any, 0, 0, 400, 200, "", #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_Invisible)
  StickyWindow(mWindow, 1)
  Make_Jelly_Window(mWindow, iColor)
  ProcedureReturn mWindow
EndProcedure



;-    Test!



OpenWindow(1, 0, 0, 500, 500, "Test Window", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)

ButtonGadget(1, 10, 10, 100, 20, "Click Me!")

Repeat
  
  dwEvent = WaitWindowEvent()
  If dwEvent = #PB_Event_Gadget
    If EventGadget() = 1
      If EventType() = #PB_EventType_LeftClick
        If Not(IsWindow(jWindow))
          jWindow = Create_Jelly_Window(300, 300, $CE7272)
          TextGadget(#PB_Any, 10, 20, 280, 20, "To close me, move your mouse into, and out of me.", #PB_Text_Center)
          StringGadget(3, 10, 50, 280, 20, "")
          ButtonGadget(2, 10, 80, 280, 20, "Or click here!")
          Show_Jelly_Window(jWindow, 500, 200, 300, 200)
          SetActiveGadget(3)
        EndIf
      EndIf
    ElseIf EventGadget() = 2
      If EventType() = #PB_EventType_LeftClick
        CloseWindow(EventWindow())
      EndIf
      
    EndIf
  EndIf
  If dwEvent = #PB_Event_CloseWindow
    CloseWindow(EventWindow())
  EndIf
  
  
Until dwEvent = #PB_Event_CloseWindow And EventWindow() = 1

End
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Nifty Fancy Window Code [Windows]

Post by electrochrisso »

Jelly Buttons, Jelly Windows, what next, Jelly Belly. :lol:
Seriously, this is pretty 8), I like the way the window slides into view. :wink:
Thanks for sharing. :)
PureBasic! Purely the best 8)
Post Reply