Toast Alert vs (my) TdesktopAlert

Toast Alert vs (my) TdesktopAlert

Postby Silvio.Falconi » Fri Apr 01, 2016 5:07 pm

Dear Antonio,
I saw the class of Cristobal called Toast but when I asked you to help me create the Desktop Alert class I showed you it was the alert window

(http://help.infragistics.com/Help/Doc/W ... Alert.html)

Image


As you can see it is totally different with the one created by Cristobal.

Cristobal is good no doubt, but the desktop alert has another design style

I was trying to do all of these features

Image

My class TDesktopAlert approaches the type of Desktop Alert that makes window and now it also allows the animation, up from the bottom and back down after n seconds


the menu can be customized by the user with this command

oAlert:aMnuUser := { {"Option1", { || MsgInfo("1") } },;
{"Option2", { || MsgInfo("2") } } }



to create the animation you need to enter this command

oAlert:Move_Alert(4)

this is the class

sample test.prg

Code: Select all  Expand view
#include "FiveWin.ch"

//----------------------------------------------------------------------------//

function Main()

   local oWnd

   DEFINE WINDOW oWnd TITLE "Click me for a desktop notification"

   ACTIVATE WINDOW oWnd ;
          ON CLICK ShowAlert()

return nil

//----------------------------------------------------------------------------//

function ShowAlert( oWnd )

   local oAlert := TDesktopAlert():New( 100, 100, 450, 160, oWnd, .T.,nRgb( 221, 236, 253 ), nRgb( 95, 131, 179 ) )

   oAlert:cHeader  = "Desktop alert"
   oAlert:cBody    = "This a sample text area."+CRLF+"This a sample text area."
   oAlert:cFoot    = "this is the footer area"

   oAlert:cBmpHeader = "C:\work\fwh\bitmaps\16x16\help.bmp"
   oAlert:cBmpFoot   = "C:\work\fwh\bitmaps\16x16\help.bmp"
   oAlert:cBmpLeft   = "C:\work\fwh\bitmaps\16x16\mail.bmp"

   oAlert:lLineHeader = .T.
   oAlert:lBorder     = .T.


   oAlert:lBtnClose   = .T.
   oAlert:lBtnDown    = .T.
   oAlert:lSplitHdr   = .T.

   oAlert:aMnuUser  := {  {"Option1", { || MsgInfo("1") } },;
                                   {"Option2", { || MsgInfo("2") } }   }


   oAlert:Move_Alert(4)

return nil
 



the last release of My TDesktop Class (created from Ttooltip of Paco)

Code: Select all  Expand view

#include "fivewin.ch"
#include "Slider.ch"
#include "constant.ch"


#define CW_USEDEFAULT      32768
#define SRCCOPY 13369376

#define DT_TOP              0x00000000
#define DT_LEFT             0x00000000
#define DT_CENTER           0x00000001
#define DT_RIGHT            0x00000002
#define DT_VCENTER          0x00000004
#define DT_BOTTOM           0x00000008
#define DT_WORDBREAK        0x00000010
#define DT_SINGLELINE       0x00000020
#define DT_EXPANDTABS       0x00000040
#define DT_TABSTOP          0x00000080
#define DT_NOCLIP           0x00000100
#define DT_EXTERNALLEADING  0x00000200
#define DT_CALCRECT         0x00000400
#define DT_NOPREFIX         0x00000800
#define DT_INTERNAL         0x00001000

#define CS_DROPSHADOW       0x00020000


//=========================================================================
//
// File:    test6
// Created:
//
// Project: desktop Alert
//
//=========================================================================



#include "FiveWin.ch"

//----------------------------------------------------------------------------//

function Main()

   local oWnd

   DEFINE WINDOW oWnd TITLE "Click me for a desktop notification"

   ACTIVATE WINDOW oWnd ;
          ON CLICK ShowAlert()

return nil

//----------------------------------------------------------------------------//

function ShowAlert( oWnd )

   local oAlert := TDesktopAlert():New( 100, 100, 450, 160, oWnd, .T.,nRgb( 221, 236, 253 ), nRgb( 95, 131, 179 ) )

   oAlert:cHeader  = "Desktop alert"
   oAlert:cBody    = "This a sample text area."+CRLF+"This a sample text area."
   oAlert:cFoot    = "this is the footer area"

   oAlert:cBmpHeader = "C:\work\fwh\bitmaps\16x16\help.bmp"
   oAlert:cBmpFoot   = "C:\work\fwh\bitmaps\16x16\help.bmp"
   oAlert:cBmpLeft   = "C:\work\fwh\bitmaps\16x16\mail.bmp"

   oAlert:lLineHeader = .T.
   oAlert:lBorder     = .T.


   oAlert:lBtnClose   = .T.
   oAlert:lBtnDown    = .T.
   oAlert:lSplitHdr   = .T.

   oAlert:aMnuUser  := {  {"Option1", { || MsgInfo("1") } },;
                         {"Option2", { || MsgInfo("2") } }   }


   oAlert:Move_Alert(4)

return nil

//----------------------------------------------------------------------------//



//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//

CLASS TDesktopAlert FROM TWindow

      CLASSDATA lRegistered AS LOGICAL

      DATA lSplitHdr    AS LOGICAL INIT .f.
      DATA lLeft        AS LOGICAL INIT .f.

      DATA lLineHeader  AS LOGICAL INIT .f.
      DATA lLineFoot    AS LOGICAL INIT .F.
      DATA lBorder      AS LOGICAL INIT .t.


      DATA cHeader      AS CHARACTER INIT  ""
      DATA cBmpLeft     AS CHARACTER INIT  ""
      DATA cBody        AS CHARACTER INIT  ""
      DATA cBmpFoot     AS CHARACTER INIT  ""
      DATA cFoot        AS CHARACTER INIT  ""
      DATA lRightAlignBody AS LOGICAL INIT .F.

      DATA cLibHeader
      DATA cBmpHeader
      DATA cLibLeft
      DATA cLibFoot
      DATA cTumbNail    AS CHARACTER INIT ""
      DATA cHeader2     AS CHARACTER INIT  space(255)

      DATA nClrPane2
      DATA nClrBorder   AS NUMERIC INIT 0
      DATA nClrSepara1  AS NUMERIC INIT RGB(157,188,219)
      DATA nClrSepara2  AS NUMERIC INIT CLR_WHITE

      DATA nClrTextHeader
      DATA nClrTextBody
      DATA nClrTextFoot

      DATA oFontHdr
      DATA oFontHdr2
      DATA oFontBody
      DATA oFontPie

      DATA aHeader   AS ARRAY INIT {0,0,0,0}
      DATA aHeader2  AS ARRAY INIT {0,0,0,0}
      DATA aBody     AS ARRAY INIT {0,0,0,0}
      DATA aLeft     AS ARRAY INIT {0,0,0,0}
      DATA aRight    AS ARRAY INIT {0,0,0,0}
      DATA aFoot     AS ARRAY INIT {0,0,0,0}
      DATA aBtnClose AS ARRAY INIT {0,0,0,0}

      DATA nWRadio
      DATA nHRadio
      DATA nGetColor

      DATA aOldPos, nOldRow, nOldCol
      DATA hRgn
      DATA nMResize

      DATA bBmpLeft

      DATA nFixWidth
      DATA nFixHeight

      DATA bOwnerDraw

      DATA oTimer, nTimer

      DATA lBtnClose       AS LOGICAL INIT .t.
      DATA aBtnClose       AS ARRAY INIT {0,0,0,0}
      DATA lOverClose      AS LOGICAL INIT .F.
      DATA lOverDown        AS LOGICAL INIT .F.
      DATA aBtndown        AS ARRAY INIT {0,0,0,0}
      DATA lBtnDown        AS LOGICAL INIT .f.

      DATA nOver
      DATA lAlert          AS LOGICAL INIT .t.
      DATA nOption
      DATA bAction


      DATA aItems
      DATA aCoors
      DATA nLevel
      DATA nDuration
      DATA aMnuUser      AS ARRAY


      METHOD New( nTop, nLeft, nWidth, nHeight, oWnd, lDisenio, nClrPane, ;
                  nClrPane2, nClrText, nWRadio, nHRadio,aItems,nLevel,aMnuUser) CONSTRUCTOR
      METHOD Default ()
      METHOD Destroy()  INLINE ::oFontHdr :End(),;
                               ::oFontHdr2:End(),;
                               ::oFontBody:End(),;
                               ::oFontPie :End(),;
                               DeleteObject( ::hRgn ),;
                               ::Super:Destroy()
      METHOD EndPaint() INLINE ::nPaintCount--,EndPaint( ::hWnd, ::cPS ), ::cPS := nil, ::hDC := nil, 0
      METHOD Display()  INLINE ::BeginPaint(),::Paint(),::EndPaint(),0
      METHOD Paint   ()
      METHOD PaintHdr ( hDC, rc )
      METHOD PaintHdr2( hDC, rc )
      METHOD PaintBody( hDC, rc )
      METHOD PaintFoot( hDC, rc )

      METHOD HandleEvent( nMsg, nWParam, nLParam )
      METHOD ReSize( nSizeType, nWidth, nHeight )
      METHOD lHeader() INLINE !empty( ::cHeader )
      METHOD lFoot()   INLINE !empty( ::cFoot )
      METHOD GetSize()
      METHOD SetSize( nWidth, nHeight ) INLINE ::Super:SetSize( nWidth, nHeight, .t. )

      METHOD BtnDown( hDC,nTop,nLeft )
      METHOD BtnClose( hDC,nTop,nLeft )
      METHOD LButtonDown( nRow, nCol, nFlags )
      METHOD MouseMove  ( nRow, nCol, nFlags )
      METHOD LButtonUp  ( nRow, nCol, nFlags )
      METHOD GetItems()
      METHOD SetItems( aItems )
      METHOD PopMenu( nRow, nCol, nKey )  // PopUp menu options
      METHOD DesktopAlertSettings
      METHOD Move_Alert(nTime)
ENDCLASS

//----------------------------------------------------------------------------//

METHOD New( nTop, nLeft, nWidth, nHeight, oWnd, lDisenio, nClrPane, nClrPane2,;
            nClrText, nWRadio, nHRadio,aItems,nLevel,aMnuUser) CLASS TDesktopAlert

   DEFAULT nClrPane  := CLR_WHITE
   DEFAULT nClrPane2 := nClrPane
   DEFAULT nClrText  := 0
   DEFAULT nWRadio   := 2
   DEFAULT nHRadio   := 2
   DEFAULT nLevel      := 180

   DEFAULT aItems    := {"close","Down"}

  ::SetItems( aItems )

   ::oWnd       = oWnd
   ::nStyle     = nOR( WS_POPUP, WS_VISIBLE )
   ::nTop       = nTop
   ::nLeft      = nLeft
   ::nBottom    = nTop + nHeight
   ::nRight     = nLeft + nWidth

   ::nClrPane   = nClrPane
   ::nClrPane2  = nClrPane2
   ::nClrText   = nClrText
   ::nClrBorder = RGB( 118,118,118 )
   ::nWRadio    = nWRadio
   ::nHRadio    = nHRadio

   ::nTimer     = 5000
   ::nLevel     = nLevel

   ::aBtnClose      := {}
   ::aBtnDown       := {}
   ::aCoors         := {}

   ::aMnuUser       := {}


   DEFINE FONT ::oFontHdr   NAME "Verdana"  SIZE 0, -11 BOLD
   DEFINE FONT ::oFontHdr2  NAME "Verdana"  SIZE 0, -11
   DEFINE FONT ::oFontBody  NAME "Segoe UI" SIZE 0, -11
   DEFINE FONT ::oFontPie   NAME "Verdana"  SIZE 0, -11 BOLD

   ::Register( nOR( CS_VREDRAW, CS_HREDRAW, CS_DROPSHADOW ) ) //, 131072

   ::Create()

   ::cTitle = "Desktop Alert"
   ::hRgn   = nil
   ::nOver        := -1

   ::nOption:= 1

   *::Default( .f. )

   ::Shadow()

   SetTransparent( self, ::nLevel )

return Self

//----------------------------------------------------------------------------//

METHOD GetSize() CLASS TDesktopAlert

   local rc        := 0
   local aSize     := { 0, 0 }
   local hBmp      := 0
   local hDC       := 0
   local hOldFont  := 0
   local n         := 0
   local nHBmp     := 0
   local nHText    := 0
   local nHeight   := 0
   local nLen      := 0
   local nW        := 0
   local nW2       := 0
   local nWB       := 0
   local nWBmp     := 0
   local nWBodyTxt := 227
   local nWF       := 0
   local nWH       := 0
   local nWidth    := 0

     if ::nFixWidth != nil .and. ::nFixHeight != nil
        return {::nFixWidth, ::nFixHeight}
     endif

     rc        := GetClientRect(::hWnd)
     nWidth    := nWBodyTxt

     // Header
     if ! Empty( ::cHeader )
        nHeight += 31
        nWH = GetTextWidth( 0, ::cHeader, ::oFontHdr:hFont ) + 16
     endif

     // Left side image
     if ! Empty( ::cBmpLeft )
        hBmp := LoadImageEx( ::cBmpLeft )
     else
       if ::bBmpLeft != nil
          hBmp = Eval( ::bBmpLeft, self )
       endif
     endif

     if hBmp != 0
        nWBmp := BmpWidth ( hBmp )
        nHBmp := BmpHeight( hBmp )
        nWidth += ( 14 + nWBmp )
        DeleteObject( hBmp )
     endif

     if Empty( ::cHeader ) .and. Empty( ::cFoot )
        nWidth = 13 + If( nWBmp != 0, ( nWBmp + 13 ), 0 ) + ;
                 GetTextWidth( 0, ::cBody, ::oFontBody:hFont ) + 26

     endif

     if ! Empty( ::cFoot )
        nHeight += 30
        nWF = GetTextWidth( 0, ::cFoot, ::oFontPie:hFont ) + 22
     endif

     nWidth = Max( Max( nWidth, nWH ), nWF )

     if Empty( ::cHeader ) .and. Empty( ::cFoot )
        nWidth = Min( nWidth, 227 )
     endif

     // if there is text in the body
     if ! Empty( ::cBody )
        hDC      = CreateDC( "DISPLAY",0,0,0)
        hOldFont = SelectObject( hDC, ::oFontBody:hFont )//
        nHText   = DrawText( hDC, AllTrim( ::cBody ),;
                             { 0, 12 + nWBmp + 12 + 10, 20, nWidth },;
                             nOr( DT_WORDBREAK, 8192, DT_CALCRECT ) )
        SelectObject( hDC, hOldFont )
        DeleteDC( hDC )
        nHeight += nHText
        nHeight +=8
     endif

     nHeight = Max( nHeight, nHBmp )

     aSize := { nWidth, nHeight }

return aSize

//----------------------------------------------------------------------------//

METHOD Default( lShowDlg ) CLASS TDesktopAlert

   local rc := {0, 0, ::nHeight, ::nWidth}
   Local hRgn
   Local hRgn2
   Local hRgn3
   local o := self

DEFAULT lShowDlg := .F.

  * o:SetPos( ScreenHeight() - rc[ 3 ], ScreenWidth( 0 ) - rc[ 4 ]-10 )

   ::hRgn = CreateRoundRectRgn( rc[ 2 ], rc[ 1 ], rc[ 4 ], rc[ 3 ], ::nWRadio,;
                                ::nHRadio )

   SetWindowRgn( ::hWnd, ::hRgn, .T. )

   DeleteObject( ::hRgn )

   return 0

//----------------------------------------------------------------------------//

METHOD Move_Alert(nTime) CLASS TDesktopAlert
  Local  oDlgheight := GetSysMetrics(1)
  Local otask:= self

   SndPlaySound( "C:\Work\fwh\sounds\alert.wav", 0 )

   for i = 1 to 20
        oDlgheight :=  oDlgheight - i
       oTask:Move(  oDlgheight, 100,  otask:nWidth, otask:nBottom+100, .t. )
       SysWait(.02)
    next

   SysWait(nTime)

   for i = 1 to 40
        oDlgheight :=  oDlgheight + i
       otask:Move(  oDlgheight, 100,  otask:nWidth, otask:nBottom+100, .t. )
       SysWait(.02)
   next
   otask:end()
   return


//----------------------------------------------------------------------------//

METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TDesktopAlert

   if nMsg == 20
      return 1
   endif

return ::Super:HandleEvent( nMsg, nWParam, nLParam )

//----------------------------------------------------------------------------//

METHOD ReSize( nSizeType, nWidth, nHeight ) CLASS TDesktopAlert

   ::Default()
   ::Refresh()

return ::Super:ReSize( nSizeType, nWidth, nHeight )

//----------------------------------------------------------------------------//

METHOD Paint() CLASS TDesktopAlert

  local hDCMem   := CreateCompatibleDC( ::hDC )
  local rc       := GetClientRect( ::hWnd )
  local hBmpMem  := CreateCompatibleBitmap( ::hDC, rc[ 4 ] - rc[ 2 ],;
                                            rc[ 3 ] - rc[ 1 ] )
  local hOldBmp  := SelectObject( hDCMem, hBmpMem )
  local nWRadio  := ::nWRadio
  local nHRadio  := ::nHRadio
  local nClrText := SetTextColor( hDCMem, ::nClrText )
  local hBrush
  local hRgn     := CreateRoundRectRgn( rc[ 2 ], rc[ 1 ], rc[ 4 ], rc[ 3 ],;
                                        ::nWRadio, ::nHRadio )

  local nLen
  local nH
  local o := self
  nLen := len( ::aItems )

             ::aCoors := array(nLen)
         for n := 1 to nLen
             ::aCoors[n] :={0,0,0,0}
           next




   if ::oTimer != nil
      ::oTimer:Deactivate()
      ::oTimer:End()
   endif

    IF ::lAlert

   DEFINE TIMER ::oTimer INTERVAL ::nTimer ACTION ::Hide() OF Self

   ACTIVATE TIMER ::oTimer

   Endif



   rc[ 3 ]--; rc[ 4 ]--
   nWRadio += 2
   nHRadio += 2

  VerticalGradient( hDCMem, { rc[ 1 ] - 1, rc[ 2 ], rc[ 3 ], rc[ 4 ] },;
                    ::nClrPane, ::nClrPane2 )

  if ::bOwnerDraw == nil
     ::PaintHdr( hDCMem, rc )
     ::PaintFoot( hDCMem, rc )
     ::PaintBody( hDCMem, rc )
  else
     Eval( ::bOwnerDraw, hDCMem )
  endif



  hBrush = CreateSolidBrush( ::nClrBorder )

  if ::lBorder
     FrameRgn( hDCMem, hRgn, hBrush, 1, 1 )
  endif

    nH      := rc[1]+20

   if ::lBtnClose
      ::BtnClose( hDCMem, (nH/2), rc[4]-12, ::lOverClose )
   endif

   if ::lBtnDown
      ::BtnDown( hDCMem, (nH/2), rc[4]-26, ::lOverDown )
   endif


  DeleteObject( hBrush )
  DeleteObject( hRgn )

  SetTextColor( hDCMem, nClrText )

  BitBlt( ::hDC, 0, 0, rc[ 4 ] - rc[ 2 ], rc[ 3 ] - rc[ 1 ], hDCMem, 0, 0, SRCCOPY )






  SelectObject( hDCMem, hOldBmp )
  DeleteDC    ( hDCMem )
  DeleteObject( hBmpMem )

return 0

//----------------------------------------------------------------------------//

METHOD PaintHdr( hDC, rc ) CLASS TDesktopAlert

   local hBmpHdr
   local nWBmpHdr := 0
   local hOldFont
   local nClrText
   local lIcon := .f.
   local nTop
   local nMode

   local nWBmpClose := 0
   local hBmpClose

   // 25 pixels
   if ::lHeader

      ::aHeader = { rc[ 1 ], rc[ 2 ], rc[ 1 ] + 25, rc[ 4 ] }

      if ::lLineHeader
         Line( hDC, ::aHeader[ 3 ], ::aHeader[ 2 ] + 5, ::aHeader[ 3 ],;
               ::aHeader[ 4 ] - 5, ::nClrSepara1 )
         Line( hDC, ::aHeader[ 3 ] + 1, ::aHeader[ 2 ] + 5, ::aHeader[ 3 ] + 1,;
               ::aHeader[ 4 ] - 5, ::nClrSepara2 )
      endif



     if ! Empty( ::cBmpHeader )
         hBmpHdr = LoadImageEx( ::cBmpHeader )
         if hBmpHdr  != 0
            nWBmpHdr = BmpWidth( hBmpHdr )
            nTop     = ( ::aHeader[ 1 ] + ;
                       ( ::aHeader[ 3 ] - ::aHeader[ 1 ] ) / 2 ) - ;
                       BmpHeight( hBmpHdr ) / 2
            nTop     = Max( nTop, 5 )
            DrawMasked( hDC, hBmpHdr, nTop, 5 )
            DeleteObject( hBmpHdr )
         endif
      endif




      hOldFont = SelectObject( hDC, ::oFontHdr:hFont )

      if ::nClrTextHeader != nil
         nClrText = SetTextColor( hDC, ::nCLrTextHeader )
      endif
      nMode = SetBkMode( hDC, 1 )

      DrawText( hDC, ::cHeader, { ::aHeader[ 1 ], ::aHeader[ 2 ] + 10 + ;
                If( hBmpHdr != 0, nWBmpHdr, 0 ), ::aHeader[ 3 ],;
                ::aHeader[ 4 ] - 10 }, nOr( DT_VCENTER, DT_SINGLELINE, 8192 ) )

      SetBkMode( hDC, nMode )

      if ::nClrTextHeader != nil
         SetTextColor( hDC, nClrText )
      endif

      SelectObject( hDC, hOldFont )
   else
      ::aHeader  := {rc[1],rc[2],rc[1],rc[4]}
   endif

return 0

//----------------------------------------------------------------------------//

METHOD PaintHdr2( hDC, rc ) CLASS TDesktopAlert

   local hOldFont
   local nClrText

   ::aHeader2 = { ::aHeader[ 3 ], rc[ 2 ], ::aHeader[ 3 ], rc[ 4 ] }

   if ::lHeader

      if ::lSplitHdr
         ::aHeader2 = { ::aHeader[ 3 ], rc[ 2 ], ::aHeader[ 3 ] + 25, rc[ 4 ] }
      endif

      if ::lLineHeader
         Line( hDC, ::aHeader2[ 3 ], ::aHeader2[ 2 ] + 5, ::aHeader2[ 3 ],;
               ::aHeader2[ 4 ] - 5, ::nClrSepara1 )
         Line( hDC, ::aHeader2[ 3 ] + 1, ::aHeader2[ 2 ] + 5, ::aHeader2[ 3 ] + 1,;
               ::aHeader2[ 4 ] - 5, ::nClrSepara2 )
      endif

      hOldFont = SelectObject( hDC, ::oFontHdr2:hFont )

      if ::nClrTextHeader != nil
         nClrText := SetTextColor( hDC, ::nCLrTextHeader )
      endif

      if ::lSplitHdr .and. ! Empty( ::cHeader2 )
         DrawText( hDC, ::cHeader2, { ::aHeader2[ 1 ] + 1, ::aHeader2[ 2 ] + 20,;
                   ::aHeader2[ 3 ], ::aHeader2[ 4 ] - 2 }, nOR( DT_WORDBREAK, 8192 ) )
      endif

      if ::nClrTextHeader != nil
         SetTextColor( hDC, nClrText )
      endif

      SelectObject( hDC, hOldFont )
  endif

return 0

//----------------------------------------------------------------------------//

METHOD PaintBody( hDC, rc ) CLASS TDesktopAlert

   local hOldFont
   local nWBmp := 0
   local nClrText
   local lIcon := .f.
   local nMode
   local hBmpLeft := 0
   local n
   local nLen
   local nW
   local nW2
   local aLeft

   ::aLeft = { 0, 0, 0, 0 }

   ::aBody = { ::aHeader[ 3 ] + If( ::lLineHeader, 5, 0 ), rc[ 2 ],;
               ::aFoot[ 1 ], rc[ 4 ] }

   if Empty( ::cBmpLeft )
      ::aLeft = { ::aBody[ 1 ], rc[ 2 ], ::aBody[ 3 ],;
                  If( ::lLeft, ( rc[ 4 ] - rc[ 2 ] ) * 0.33, rc[ 2 ] ) }
   else
      hBmpLeft = LoadImageEx( ::cBmpLeft )
      if hBmpLeft != 0
         nWBmp = BmpWidth( hBmpLeft )
         ::aLeft = { ::aBody[ 1 ], rc[ 2 ], ::aBody[ 3 ], 12 + nWBmp + 12 }
      endif
   endif

   if ::bBmpLeft != nil
      hBmpLeft = Eval( ::bBmpLeft, self )
      if hBmpLeft != 0
         nWBmp = BmpWidth( hBmpLeft )
         ::aLeft = { ::aBody[ 1 ], rc[ 2 ], ::aBody[ 3 ], 12 + nWBmp + 12 }
      endif
   endif

   ::aRight = { ::aBody[ 1 ] + 3, ::aLeft[ 4 ] + 20, ::aBody[ 3 ] - 3, rc[ 4 ] - 10 }

   hOldFont = SelectObject( hDC, ::oFontBody:hFont )

   nMode = SetBkMode( hDC, 1 )

   DrawText( hDC, AllTrim( ::cBody ), ::aRight,;
             nOr( If( ::lRightAlignBody, DT_RIGHT, DT_LEFT ), DT_WORDBREAK ) )

   SetBkMode( hDC, nMode )

   SelectObject( hDC, hOldFont )

   if hBmpLeft != 0
      DrawMasked( hDC, hBmpLeft, ::aLeft[ 1 ] + 5, ::aLeft[ 2 ] + 12 )
      DeleteObject( hBmpLeft )
   endif

return 0

//----------------------------------------------------------------------------//

METHOD PaintFoot( hDC, rc ) CLASS TDesktopAlert

   local hOldFont, hBmpFoot
   local nWFoot := 0
   local nClrText
   local lIcon := .f.
   local nMode

   if ::lFoot
      ::aFoot = { rc[ 3 ] - 30, rc[ 2 ], rc[ 3 ], rc[ 4 ] }
      if ! Empty( ::cBmpFoot )
         ::aFoot = { rc[ 3 ] - 30, rc[ 2 ], rc[ 3 ], rc[ 4 ] }
      endif
      hBmpFoot = LoadImageEx( ::cBmpFoot )
      if hBmpFoot != 0
         nWFoot = BmpWidth( hBmpFoot )
         ::aFoot = { rc[ 3 ] - 30, rc[ 2 ], rc[ 3 ], rc[ 4 ] }
         DrawMasked( hDC, hBmpFoot,;
                     ( ::aFoot[ 1 ] + ( ::aFoot[ 3 ] - ::aFoot[ 1 ] ) / 2 ) - ;
                     BmpHeight( hBmpFoot ) / 2, 5 )
         DeleteObject( hBmpFoot )
      endif
    else
       ::aFoot = { rc[ 3 ], rc[ 2 ], rc[ 3 ], rc[ 4 ] }
    endif

    if ::lFoot
       hOldFont = SelectObject( hDC, ::oFontPie:hFont )
       if ::nClrTextFoot != nil
          nClrText = SetTextColor( hDC, ::nClrTextFoot )
       endif
       nMode = SetBkMode( hDC, 1 )
       DrawText( hDC, ::cFoot, { ::aFoot[ 1 ], ::aFoot[ 2 ] + 10 + nWFoot,;
                 ::aFoot[ 3 ], ::aFoot[ 4 ] }, nOr( DT_VCENTER, DT_SINGLELINE, 8192 ) )
       SetBkMode( hDC, nMode )
       if ::nClrTextFoot != nil
          SetTextColor( hDC, nClrText )
       endif
      SelectObject( hDC, hOldFont )
   endif

   Line( hDC, ::aFoot[ 1 ], ::aFoot[ 2 ] + 5, ::aFoot[ 1 ], ::aFoot[ 4 ] - 5,;
         ::nClrSepara1 )
   Line( hDC, ::aFoot[ 1 ] + 1, ::aFoot[ 2 ] + 5, ::aFoot[ 1 ] + 1,;
         ::aFoot[ 4 ] - 5, ::nClrSepara2 )

   return 0


//----------------------------------------------------------------------------//
METHOD BtnClose( hDC,nTop,nLeft ) CLASS TDesktopAlert

::aBtnClose := closebutton( hDC, nTop, nLeft, ::lOverClose )
::aItems[1,3] := ::aBtnClose
  return 0

//----------------------------------------------------------------------------//
METHOD BtnDown( hDC,nTop,nLeft ) CLASS TDesktopAlert

::aBtndown := DropDownbutton( hDC, nTop, nLeft, ::lOverDown )
::aItems[2,3] := ::aBtndown
return 0

//----------------------------------------------------------------------------//
 METHOD LButtonDown( nRow, nCol, nFlags ) CLASS TDesktopAlert

    if ::lOverClose
       ::End()
    endif

      if ::lOverDown
            ::PopMenu( nRow, nCol, nFlags )
      endif

    return 0

//----------------------------------------------------------------------------//

METHOD MouseMove  ( nRow, nCol, nFlags ) CLASS TDesktopAlert

local nOver := ::nOver
local n
local nLen := len(::aCoors)
local lFindclose := .f.
local lFindDown := .f.

for n := 1 to nLen

    if PtInRect( nRow, nCol, ::aBtnClose )
       lFindClose := .t.
       ::nOver := 1
       if nOver != 1
          //::Refresh(.f.)
       endif
       exit
    endif


     if PtInRect( nRow, nCol, ::aBtnDown )
       lFindDown := .t.
       ::nOver := 2
       if nOver != 2
          //::Refresh(.f.)
       endif
       exit
    endif


next

::lOverClose := ::nOver > 0 .and. PtInRect( nRow, nCol, ::aItems[1,3] )

::lOverDown := ::nOver > 0 .and. PtInRect( nRow, nCol, ::aItems[2,3] )

if lFindClose    .or. lFindDown

   if ::lOverClose  .or. ::lOverDown
      CursorHand()
   else
      CursorArrow()
   endif

else
   ::nOver := -1
   CursorArrow()
endif

if nOver != ::nOver
   ::Refresh(.f.)
endif


return 0
//----------------------------------------------------------------------------//

   METHOD LButtonUp  ( nRow, nCol, nFlags ) CLASS TDesktopAlert

/*if ::nOver > 0
   if ::lOverClose
      ::aItems[1,2] := .t.
   else
      ::nOption := ::nOver
      if ::bAction != nil
         eval(::bAction, ::nOption, ::aItems[::nOption,1])
      endif
   endif
   ::Refresh()
endif
*/


return 0


//----------------------------------------------------------------------------//

METHOD PopMenu( nRow, nCol, nKey ) CLASS TDesktopAlert
   LOCAL oPopup
   local i
   local nLen := len( ::aMnuUser )



   MENU oPopUp POPUP

  IF nLen >0
       For i := 1 to nLen
            bAction :=  ::aMnuUser[i][2]
           MENUITEM RTrim(::aMnuUser[i][1]) BLOCK bAction
        Next i
        SEPARATOR
     endif


       MENUITEM "Desktop Alert Settimgs" ACTION ::DeskTopAlertSettings()
   ENDMENU


   ACTIVATE POPUP oPopup OF Self AT nRow, nCol


   return nil








//----------------------------------------------------------------------------//

 METHOD SetItems( aItems ) CLASS TDesktopAlert

    local n
    local nLen

    if len(aItems) != 0

       ::aItems := {}

       for n := 1 to len(aItems)
           aadd(::aItems, {aItems[n], .f.,{0,0,0,0}} )
       next

    endif

return 0

//----------------------------------------------------------------------------//


  METHOD GetItems() CLASS TDesktopAlert

local n
local nLen := len(::aItems)
local aItems := {}

for n := 1 to nLen
    if ::aItems[n,2]
       aadd(aItems, ::aItems[n,1] )
    endif
next

return aItems
//----------------------------------------------------------------------------//

METHOD DesktopAlertSettings  CLASS TDesktopAlert
   Local oDlgSettings
   Local nDuration := ::nTimer
   Local ntransparency := ::nLevel
   local oDuration,oTrans
   Local cText_Duration:= FWString("How long should the desktop alert appear ?" )
   local cText_transparency:= FWString("How transparency should the desktop be ?")
   local obtn[3]
   local oGrp[2]
   local oSay[4]
   Local nBottom   := 20
   Local nRight    := 62
   Local nWidth :=  Max( nRight * DLG_CHARPIX_W, 180 )
   Local nHeight := nBottom * DLG_CHARPIX_H
   local oThis := self




   DEFINE DIALOG oDlgSettings  SIZE nWidth, nHeight   PIXEL TITLE FWString( "DesktopAlert Settings" )
   oDlgSettings:lTruePixel := .f.


@ 0, 2 GROUP oGrp[1] PROMPT FWString("Duration ( 0 - 5 seconds )") OF oDlgSettings SIZE 210,48
@ 4, 2 GROUP oGrp[2] PROMPT FWString("Transparency") OF oDlgSettings SIZE 210,51

@ 0.5, 6 SAY oSay[1] PROMPT cText_Duration OF oDlgSettings   SIZE 180,10
@ 4.2, 6 SAY oSay[2] PROMPT cText_transparency OF oDlgSettings SIZE 180,10


@ 22, 20 SLIDER oDuration VAR nDuration OF oDlgSettings ;
               HORIZONTAL ;
               RIGHT DIRECTION ;
               RANGE 1000, 5000 ;  // 0 = NO close
               MARKS 6;
               EXACT;
               ON CHANGE  oSay[3]:settext(str(nDuration)+FWString("seconds")) ;
               SIZE 200, 12 PIXEL

 @ 38, 96 SAY oSay[3] PROMPT  str(nDuration)+FWString("seconds") OF oDlgSettings   SIZE 120,10 pixel


@ 80, 20 SLIDER oTrans VAR ntransparency OF oDlgSettings ;
               HORIZONTAL ;
               RIGHT DIRECTION ;
               RANGE 100, 300 ;
               MARKS 11;
               EXACT;
               ON CHANGE   oSay[4]:settext(str(ntransparency)+FWString(" trasparency level")) ;
               SIZE 200, 12 PIXEL

@ 96, 96 SAY oSay[4] PROMPT  str(ntransparency)+FWString(" trasparency level")  OF oDlgSettings SIZE 120,10      pixel



@ 118, 14 BUTTON obtn[1] PROMPT FWString("&Preview") SIZE 45,12  OF oDlgSettings PIXEL   action (::nLevel := ntransparency,oThis:Display())
@ 118, 94 BUTTON obtn[2] PROMPT FWString("&Ok") SIZE 45,12  OF oDlgSettings PIXEL       action  oDlgSettings:End(IDOK)
@ 118, 164 BUTTON obtn[3] PROMPT FWString("&Cancel") SIZE 45,12  OF oDlgSettings PIXEL  action  oDlgSettings:End(IDCANCEL)



ACTIVATE DIALOG oDlgSettings CENTERED

IF oDlgSettings:nresult == IDOK

 *  msginfo( "Transp. : " + STR( ::nLevel), "Seconds : " + STR( ::nTimer ) )

       ::nTimer := nDuration
       ::nLevel := ntransparency


Endif




return nil

















       ACTIVATE DIALOG oDlgSettings CENTERED
return nil





//----------------------------------------------------------------------------//
// Functions
//----------------------------------------------------------------------------//

static function Line( hDC, nTop, nLeft, nBottom, nRight, nColor, nWidth )

   local hPen, hOldPen

   DEFAULT nColor := CLR_BLACK, nWidth := 1

   hPen = CreatePen( PS_SOLID, nWidth, nColor )
   hOldPen = SelectObject( hDC, hPen )

   MoveTo( hDC, nLeft, nTop )
   LineTo( hDC, nRight, nTop )

   SelectObject( hDC, hOldPen )
   DeleteObject( hPen )

return 0

//----------------------------------------------------------------------------//

Static Function DropDownbutton( hDC, nTop, nLeft, lOver )
local oFont, hOldFont
local aRect
local nMode

// create a  arrow down button

DEFAULT lOver := .f.

  nMode    := SetBkMode( hDC, 1 )
  oFont := TFont():New( "Marlett", 0, -10, .f.,.f.,,,,.f.,.f.,.f., 1 )
  hOldFont := SelectObject( hDC, oFont:hFont )
  aRect := {nTop,nLeft,nTop+10,nLeft+ 9}
  TextOut( hDC, aRect[1]+1, aRect[2], "u" )
  SelectObject( hDC, hOldFont  )
  oFont:End()
  SetBkMode( hDC, nMode )
  if lOver
     Box(hDC,aRect)
  endif
  return aRect

//---------------------------------------------------------------------------//

Static Function closebutton( hDC, nTop, nLeft, lOver )
local oFont, hOldFont
local aRect
local nMode

// create a X button

DEFAULT lOver := .f.

  nMode    := SetBkMode( hDC, 1 )
  oFont := TFont():New( "Marlett", 0, -10, .f.,.f.,,,,.f.,.f.,.f., 1 )
  hOldFont := SelectObject( hDC, oFont:hFont )
  aRect := {nTop,nLeft,nTop+10,nLeft+ 9}
  TextOut( hDC, aRect[1]+1, aRect[2], "r" )
  SelectObject( hDC, hOldFont  )
  oFont:End()
  SetBkMode( hDC, nMode )
  if lOver
     Box(hDC,aRect)
  endif
  return aRect
//---------------------------------------------------------------------------//


    #define GWL_EXSTYLE   -20
    #define WS_EX_LAYERED 524288

static function SetTransparent( oDlg,nLevel )

   DEFAULT   nLevel := 160

       SetWindowLong( oDlg:hWnd, GWL_EXSTYLE, nOr( GetWindowLong( oDlg:hWnd, GWL_EXSTYLE ), WS_EX_LAYERED ) )

       SetLayeredWindowAttributes( oDlg:hWnd, 0, nLevel, 2 )

    return nil

//---------------------------------------------------------------------------//

 
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6774
Joined: Thu Oct 18, 2012 7:17 pm

Re: Toast Alert vs (my) TdesktopAlert

Postby cnavarro » Fri Apr 01, 2016 6:34 pm

Silvio, yes, you are right if you use style office 2007
As we have commented by mail, to the TToast class still has some things to improve
Your class is very good and I like it a lot too, but, I followed these instructions

There are really only 4 styles notification
https://msdn.microsoft.com/es-es/librar ... s/hh761494

https://msdn.microsoft.com/es-es/librar ... mplatetype
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6500
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Toast Alert vs (my) TdesktopAlert

Postby Silvio.Falconi » Sat Apr 02, 2016 9:24 am

yes of course, but on the first page I see this :

Image


but it is that of Microsoft say


but on another guide I saw there are buttons and setup, and the toast come in with animation

Image


here there is also the api

https://github.com/tadeuszwojcik/win-notify

api
https://msdn.microsoft.com/en-US/librar ... -snippet-1
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6774
Joined: Thu Oct 18, 2012 7:17 pm

Re: Toast Alert vs (my) TdesktopAlert

Postby cnavarro » Sat Apr 02, 2016 10:17 am

Silvio, yes
In testoast, the example appears with the 4 types of notifications
And do not confuse Tiles with Toast

Please, Help me to complete the class
As we have commented, to the TToast class still has some things to improve
Image
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6500
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Toast Alert vs (my) TdesktopAlert

Postby Silvio.Falconi » Sat Apr 02, 2016 11:31 am

As I wrote on private mail
here on Windows seven (on win 8 , win10 I have the same errors) your class or toastteat.prg have many error

Image


Image


Image


Image
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6774
Joined: Thu Oct 18, 2012 7:17 pm

Re: Toast Alert vs (my) TdesktopAlert

Postby Silvio.Falconi » Sat Apr 02, 2016 11:33 am

I think we must reinit from original ttooltip class... or from antonio's sample test

viewtopic.php?f=3&t=32059&start=0&hilit=desktop+alert

and insert this feature (animation)

viewtopic.php?f=3&t=32082
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6774
Joined: Thu Oct 18, 2012 7:17 pm

Re: Toast Alert vs (my) TdesktopAlert

Postby cnavarro » Sat Apr 02, 2016 11:43 am

Yes, at moment, try with
For background colors buttons
Code: Select all  Expand view


:nClrTextHeader := CLR_WHITE
 


For error with DATA lBorder
Please replace with lDrawBorder
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6500
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Toast Alert vs (my) TdesktopAlert

Postby Silvio.Falconi » Sat Apr 02, 2016 11:47 am

FOUND TaskbarNotifier.cpp

Code: Select all  Expand view

// TaskbarNotifier.cpp : implementation file
// By John O'Byrne - 05 July 2002

#include "stdafx.h"
#include "TaskbarNotifier.h"

#define IDT_HIDDEN      0
#define IDT_APPEARING       1
#define IDT_WAITING     2
#define IDT_DISAPPEARING    3

#define TASKBAR_ON_TOP      1
#define TASKBAR_ON_LEFT     2
#define TASKBAR_ON_RIGHT    3
#define TASKBAR_ON_BOTTOM   4

// CTaskbarNotifier

IMPLEMENT_DYNAMIC(CTaskbarNotifier, CWnd)
CTaskbarNotifier::CTaskbarNotifier()
{
    m_strCaption="";
    m_pWndParent=NULL;
    m_bMouseIsOver=FALSE;
    m_hSkinRegion=NULL;
    m_hCursor=NULL;
    m_crNormalTextColor=RGB(133,146,181);
    m_crSelectedTextColor=RGB(10,36,106);
    m_nSkinHeight=0;
    m_nSkinWidth=0;
   
    m_dwTimeToShow=0;
    m_dwTimeToLive=0;
    m_dwTimeToHide=0;
    m_dwDelayBetweenShowEvents=0;
    m_dwDelayBetweenHideEvents=0;
    m_nStartPosX=0;
    m_nStartPosY=0;
    m_nCurrentPosX=0;
    m_nCurrentPosY=0;
    m_nIncrement=2;
    m_nTaskbarPlacement=0;
    m_nAnimStatus=IDT_HIDDEN;
    m_rcText.SetRect(0,0,0,0);
}

CTaskbarNotifier::~CTaskbarNotifier()
{
    // No need to delete the HRGN,  SetWindowRgn() owns it after being called
}

int CTaskbarNotifier::Create(CWnd *pWndParent, int nOrder)
{
    m_pWndParent = pWndParent;
    m_Order = nOrder;
    CString strWndClass = AfxRegisterWndClass(0,AfxGetApp()->LoadStandardCursor(IDC_ARROW),GetSysColorBrush(COLOR_WINDOW),NULL);
    return CreateEx(0,strWndClass,NULL,WS_POPUP | WS_EX_TOPMOST, 0, 0, 0, 0, pWndParent->m_hWnd, NULL);
}

void CTaskbarNotifier::SetTextFont(LPCTSTR szFont,int nSize,int nNormalStyle,int nSelectedStyle)
{
    LOGFONT lf;
    m_myNormalFont.DeleteObject();
    m_myNormalFont.CreatePointFont(nSize,szFont);
    m_myNormalFont.GetLogFont(&lf);
   
    // We  set the Font of the unselected ITEM
    if (nNormalStyle & TN_TEXT_BOLD)
        lf.lfWeight = FW_BOLD;
    else
        lf.lfWeight = FW_NORMAL;
   
    if (nNormalStyle & TN_TEXT_ITALIC)
        lf.lfItalic=TRUE;
    else
        lf.lfItalic=FALSE;
   
    if (nNormalStyle & TN_TEXT_UNDERLINE)
        lf.lfUnderline=TRUE;
    else
        lf.lfUnderline=FALSE;

    m_myNormalFont.DeleteObject();
    m_myNormalFont.CreateFontIndirect(&lf);
   
    // We set the Font of the selected ITEM
    if (nSelectedStyle & TN_TEXT_BOLD)
        lf.lfWeight = FW_BOLD;
    else
        lf.lfWeight = FW_NORMAL;
   
    if (nSelectedStyle & TN_TEXT_ITALIC)
        lf.lfItalic=TRUE;
    else
        lf.lfItalic=FALSE;
   
    if (nSelectedStyle & TN_TEXT_UNDERLINE)
        lf.lfUnderline=TRUE;
    else
        lf.lfUnderline=FALSE;

    m_mySelectedFont.DeleteObject();
    m_mySelectedFont.CreateFontIndirect(&lf);
}

void CTaskbarNotifier::SetTextColor(COLORREF crNormalTextColor,COLORREF crSelectedTextColor)
{
    m_crNormalTextColor=crNormalTextColor;
    m_crSelectedTextColor=crSelectedTextColor;
    RedrawWindow();
}

void CTaskbarNotifier::SetTextRect(RECT rcText)
{
    m_rcText=rcText;
}

BOOL CTaskbarNotifier::SetSkin(UINT nBitmapID,short red,short green,short blue)
{
    BITMAP bm;
   
    m_biSkinBackground.DeleteObject();

    if (!m_biSkinBackground.LoadBitmap(nBitmapID))
        return FALSE;
    GetObject(m_biSkinBackground.GetSafeHandle(), sizeof(bm), &bm);
    m_nSkinWidth=bm.bmWidth;
    m_nSkinHeight=bm.bmHeight;
    m_rcText.SetRect(0,0,bm.bmWidth,bm.bmHeight);

    if (red!=-1 && green!=-1 && blue!=-1)
    {
        // No need to delete the HRGN,  SetWindowRgn() owns it after being called
        m_hSkinRegion=GenerateRegion((HBITMAP)m_biSkinBackground.GetSafeHandle(),(BYTE) red,(BYTE) green,(BYTE) blue);
        SetWindowRgn(m_hSkinRegion, true);
    }

    return TRUE;
}

BOOL CTaskbarNotifier::SetSkin(LPCTSTR szFileName,short red,short green,short blue)
{
    BITMAP bm;
    HBITMAP hBmp;
   
    hBmp=(HBITMAP) ::LoadImage(AfxGetInstanceHandle(),szFileName,IMAGE_BITMAP,0,0, LR_LOADFROMFILE);
    if (!hBmp)
        return FALSE;

    m_biSkinBackground.DeleteObject();
    m_biSkinBackground.Attach(hBmp);
    GetObject(m_biSkinBackground.GetSafeHandle(), sizeof(bm), &bm);
    m_nSkinWidth=bm.bmWidth;
    m_nSkinHeight=bm.bmHeight;
    m_rcText.SetRect(0,0,bm.bmWidth,bm.bmHeight);

    if (red!=-1 && green!=-1 && blue!=-1)
    {
        // No need to delete the HRGN,  SetWindowRgn() owns it after being called
        m_hSkinRegion=GenerateRegion((HBITMAP)m_biSkinBackground.GetSafeHandle(),(BYTE) red,(BYTE) green,(BYTE) blue);
        SetWindowRgn(m_hSkinRegion, true);
    }

    return TRUE;
}

BOOL CTaskbarNotifier::SetSkin(HBITMAP hd, short red, short green, short blue)
{
    if (!hd)
    {
        return FALSE;
    }

    BITMAP bm;

    m_biSkinBackground.DeleteObject();
    m_biSkinBackground.Attach(hd);
    GetObject(m_biSkinBackground.GetSafeHandle(), sizeof(bm), &bm);
    m_nSkinWidth=bm.bmWidth;
    m_nSkinHeight=bm.bmHeight;
    m_rcText.SetRect(0,0,bm.bmWidth,bm.bmHeight);

    if (red!=-1 && green!=-1 && blue!=-1)
    {
        // No need to delete the HRGN,  SetWindowRgn() owns it after being called
        m_hSkinRegion=GenerateRegion((HBITMAP)m_biSkinBackground.GetSafeHandle(),(BYTE) red,(BYTE) green,(BYTE) blue);
        SetWindowRgn(m_hSkinRegion, true);
    }

    return TRUE;
}

void CTaskbarNotifier::Show(LPCTSTR szCaption,DWORD dwTimeToShow,DWORD dwTimeToLive,DWORD dwTimeToHide,int nIncrement)
{
    unsigned int nDesktopHeight;
    unsigned int nDesktopWidth;
    unsigned int nScreenWidth;
    unsigned int nScreenHeight;
    CRect rcDesktop;

    m_strCaption=szCaption;
    m_dwTimeToShow=dwTimeToShow;
    m_dwTimeToLive=dwTimeToLive;
    m_dwTimeToHide=dwTimeToHide;

    ::SystemParametersInfo(SPI_GETWORKAREA,0,&rcDesktop,0);
    nDesktopWidth=rcDesktop.right-rcDesktop.left;
    nDesktopHeight=rcDesktop.bottom-rcDesktop.top;
    nScreenWidth=::GetSystemMetrics(SM_CXSCREEN);
    nScreenHeight=::GetSystemMetrics(SM_CYSCREEN);

    BOOL bTaskbarOnRight=nDesktopWidth<nScreenWidth && rcDesktop.left==0;
    BOOL bTaskbarOnLeft=nDesktopWidth<nScreenWidth && rcDesktop.left!=0;
    BOOL bTaskBarOnTop=nDesktopHeight<nScreenHeight && rcDesktop.top!=0;
    BOOL bTaskbarOnBottom=nDesktopHeight<nScreenHeight && rcDesktop.top==0;
   
    switch (m_nAnimStatus)
    {
        case IDT_HIDDEN:
            BOOL b;
            DWORD dwErr;
            b = ShowWindow(SW_SHOW);
            if (!b)
            {
                dwErr = GetLastError();
            }
            if (bTaskbarOnRight)
            {
                m_dwDelayBetweenShowEvents=m_dwTimeToShow/(m_nSkinWidth/m_nIncrement)
                m_dwDelayBetweenHideEvents=m_dwTimeToHide/(m_nSkinWidth/m_nIncrement);
                m_nStartPosX=rcDesktop.right;
                m_nStartPosY=rcDesktop.bottom-m_nSkinHeight * m_Order;
                m_nTaskbarPlacement=TASKBAR_ON_RIGHT;
            }
            else if (bTaskbarOnLeft)
            {
                m_dwDelayBetweenShowEvents=m_dwTimeToShow/(m_nSkinWidth/m_nIncrement);
                m_dwDelayBetweenHideEvents=m_dwTimeToHide/(m_nSkinWidth/m_nIncrement);
                m_nStartPosX=rcDesktop.left-m_nSkinWidth * m_Order;
                m_nStartPosY=rcDesktop.bottom-m_nSkinHeight * m_Order;
                m_nTaskbarPlacement=TASKBAR_ON_LEFT;
            }
            else if (bTaskBarOnTop)
            {
                m_dwDelayBetweenShowEvents=m_dwTimeToShow/(m_nSkinHeight/m_nIncrement);
                m_dwDelayBetweenHideEvents=m_dwTimeToHide/(m_nSkinHeight/m_nIncrement);
                m_nStartPosX=rcDesktop.right-m_nSkinWidth;
                m_nStartPosY=rcDesktop.top-m_nSkinHeight;
                m_nTaskbarPlacement=TASKBAR_ON_TOP;
            }
            else //if (bTaskbarOnBottom)
            {
                // Taskbar is on the bottom or Invisible
                m_dwDelayBetweenShowEvents=m_dwTimeToShow/(m_nSkinHeight/m_nIncrement);
                m_dwDelayBetweenHideEvents=m_dwTimeToHide/(m_nSkinHeight/m_nIncrement);
                m_nStartPosX = rcDesktop.right-m_nSkinWidth;
                m_nStartPosY = rcDesktop.bottom - m_nSkinHeight * m_Order;
                m_nTaskbarPlacement=TASKBAR_ON_BOTTOM;
            }

            m_nCurrentPosX=m_nStartPosX;
            m_nCurrentPosY=m_nStartPosY;
   
            SetTimer(IDT_APPEARING,m_dwDelayBetweenShowEvents,NULL);
            break;

        case IDT_WAITING:
            RedrawWindow();
            KillTimer(IDT_WAITING);
            SetTimer(IDT_WAITING,m_dwTimeToLive,NULL);
            break;

        case IDT_APPEARING:
            RedrawWindow();
            break;

        case IDT_DISAPPEARING:
            KillTimer(IDT_DISAPPEARING);
            SetTimer(IDT_WAITING,m_dwTimeToLive,NULL);
            if (bTaskbarOnRight)
                m_nCurrentPosX=rcDesktop.right-m_nSkinWidth;
            else if (bTaskbarOnLeft)
                m_nCurrentPosX=rcDesktop.left;
            else if (bTaskBarOnTop)
                m_nCurrentPosY=rcDesktop.top;
            else //if (bTaskbarOnBottom)
                m_nCurrentPosY=rcDesktop.bottom-m_nSkinHeight;
           
            SetWindowPos(&wndTopMost,m_nCurrentPosX,m_nCurrentPosY,m_nSkinWidth,m_nSkinHeight,SWP_NOOWNERZORDER/* | SWP_NOZORDER*/ | SWP_NOACTIVATE);
            RedrawWindow();
            break;
    }
}

void CTaskbarNotifier::Hide()
{
    switch (m_nAnimStatus)
    {
        case IDT_APPEARING:
            KillTimer(IDT_APPEARING);
            break;
        case IDT_WAITING:
            KillTimer(IDT_WAITING);
            break;
        case IDT_DISAPPEARING:
            KillTimer(IDT_DISAPPEARING);
            break;
    }
    MoveWindow(0,0,0,0);
    ShowWindow(SW_HIDE);
    m_nAnimStatus=IDT_HIDDEN;
}

HRGN CTaskbarNotifier::GenerateRegion(HBITMAP hBitmap, BYTE red, BYTE green, BYTE blue)
{
    WORD wBmpWidth,wBmpHeight;
    HRGN hRgn, hTmpRgn;

    // 24bit pixels from the bitmap
    BYTE *pPixels = Get24BitPixels(hBitmap, &wBmpWidth, &wBmpHeight);
    if (!pPixels) return NULL;

    // create our working region
    hRgn = CreateRectRgn(0,0,wBmpWidth,wBmpHeight);
    if (!hRgn) { delete pPixels; return NULL; }

    DWORD p=0;
    for (WORD y=0; y<wBmpHeight; y++)
    {
        for (WORD x=0; x<wBmpWidth; x++)
        {
            BYTE jRed   = pPixels[p+2];
            BYTE jGreen = pPixels[p+1];
            BYTE jBlue  = pPixels[p+0];

            if (jRed==red && jGreen==green && jBlue==blue)
            {
                // remove transparent color from region
                hTmpRgn = CreateRectRgn(x,y,x+1,y+1);
                CombineRgn(hRgn, hRgn, hTmpRgn, RGN_XOR);
                DeleteObject(hTmpRgn);
            }

            // next pixel
            p+=3;
        }
    }

    // release pixels
    delete pPixels;

    // return the region
    return hRgn;
}

BYTE* CTaskbarNotifier::Get24BitPixels(HBITMAP pBitmap, WORD *pwWidth, WORD *pwHeight)
{
    BITMAP bmpBmp;
    LPBITMAPINFO pbmiInfo;
    BITMAPINFO bmiInfo;
    WORD wBmpWidth, wBmpHeight;

    GetObject(pBitmap, sizeof(bmpBmp),&bmpBmp);
    pbmiInfo   = (LPBITMAPINFO)&bmpBmp;

    wBmpWidth  = (WORD)pbmiInfo->bmiHeader.biWidth;
    wBmpWidth -= (wBmpWidth%4);
    wBmpHeight = (WORD)pbmiInfo->bmiHeader.biHeight;

    *pwWidth  = wBmpWidth;
    *pwHeight = wBmpHeight;
   
    BYTE *pPixels = new BYTE[wBmpWidth*wBmpHeight*3];
    if (!pPixels) return NULL;

    HDC hDC =::GetWindowDC(NULL);

    bmiInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmiInfo.bmiHeader.biWidth = wBmpWidth;
    bmiInfo.bmiHeader.biHeight = -wBmpHeight;
    bmiInfo.bmiHeader.biPlanes = 1;
    bmiInfo.bmiHeader.biBitCount = 24;
    bmiInfo.bmiHeader.biCompression = BI_RGB;
    bmiInfo.bmiHeader.biSizeImage = wBmpWidth*wBmpHeight*3;
    bmiInfo.bmiHeader.biXPelsPerMeter = 0;
    bmiInfo.bmiHeader.biYPelsPerMeter = 0;
    bmiInfo.bmiHeader.biClrUsed = 0;
    bmiInfo.bmiHeader.biClrImportant = 0;

    // get pixels from the original bitmap converted to 24bits
    int iRes = GetDIBits(hDC,pBitmap,0,wBmpHeight,(LPVOID)pPixels,&bmiInfo,DIB_RGB_COLORS);

    // release the device context
    ::ReleaseDC(NULL,hDC);

    // if failed, cancel the operation.
    if (!iRes)
    {
        delete pPixels;
        return NULL;
    };

    // return the pixel array
    return pPixels;
}

BEGIN_MESSAGE_MAP(CTaskbarNotifier, CWnd)
    ON_WM_CREATE()
    ON_WM_MOUSEMOVE()
    ON_WM_DESTROY()
    ON_WM_ERASEBKGND()
    ON_WM_PAINT()
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
    ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
    ON_WM_SETCURSOR()
    ON_WM_LBUTTONUP()
    ON_WM_TIMER()
END_MESSAGE_MAP()


// CTaskbarNotifier message handlers

int CTaskbarNotifier::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    m_hCursor = ::LoadCursor(NULL, MAKEINTRESOURCE(32649));
    return 0;
}

void CTaskbarNotifier::OnDestroy()
{
    CWnd::OnDestroy();

    // TODO: Add your message handler code here
}

void CTaskbarNotifier::OnMouseMove(UINT nFlags, CPoint point)
{
    TRACKMOUSEEVENT t_MouseEvent;
    t_MouseEvent.cbSize      = sizeof(TRACKMOUSEEVENT);
    t_MouseEvent.dwFlags     = TME_LEAVE | TME_HOVER;
    t_MouseEvent.hwndTrack   = m_hWnd;
    t_MouseEvent.dwHoverTime = 1;

    ::_TrackMouseEvent(&t_MouseEvent);

    CWnd::OnMouseMove(nFlags, point);
}

void CTaskbarNotifier::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_pWndParent->SendMessage(WM_TASKBARNOTIFIERCLICKED, m_Type, m_AppValue);
    Hide();
    CWnd::OnLButtonUp(nFlags, point);
}

LRESULT CTaskbarNotifier::OnMouseHover(WPARAM w, LPARAM l)
{
    if (m_bMouseIsOver==FALSE)
    {
        m_bMouseIsOver=TRUE;
        RedrawWindow();
    }
    return 0;
}

LRESULT CTaskbarNotifier::OnMouseLeave(WPARAM w, LPARAM l)
{
    if (m_bMouseIsOver==TRUE)
    {
        m_bMouseIsOver=FALSE;
        RedrawWindow();
    }
    return 0;
}

BOOL CTaskbarNotifier::OnEraseBkgnd(CDC* pDC)
{
    CDC memDC;
    CBitmap *pOldBitmap;
    BITMAP bm;

    memDC.CreateCompatibleDC(pDC);
    GetObject(m_biSkinBackground.GetSafeHandle(), sizeof(bm), &bm);
    pOldBitmap=memDC.SelectObject(&m_biSkinBackground);

    pDC->BitBlt(0,0,bm.bmWidth,bm.bmHeight,&memDC,0,0,SRCCOPY);
    memDC.SelectObject(pOldBitmap);

    return TRUE;
}

void CTaskbarNotifier::OnPaint()
{
    CPaintDC dc(this);
    CRect rcClient;
    CFont *pOldFont;
    char *szBuffer;
       
    if (m_bMouseIsOver)
    {
        dc.SetTextColor(m_crSelectedTextColor);
        pOldFont=dc.SelectObject(&m_mySelectedFont);
    }
    else
    {
        dc.SetTextColor(m_crNormalTextColor);
        pOldFont=dc.SelectObject(&m_myNormalFont);
    }

    szBuffer=new char[m_strCaption.GetLength()+10];
    strcpy(szBuffer,m_strCaption);

    dc.SetBkMode(TRANSPARENT);
    rcClient.DeflateRect(10,20,10,20);
    dc.DrawText(szBuffer,-1,m_rcText,DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_END_ELLIPSIS);
   
    delete[] szBuffer;
    dc.SelectObject(pOldFont);
}

BOOL CTaskbarNotifier::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    if (nHitTest == HTCLIENT)
    {
        ::SetCursor(m_hCursor);
        return TRUE;
    }
    return CWnd::OnSetCursor(pWnd, nHitTest, message);
}

void CTaskbarNotifier::OnTimer(UINT nIDEvent)
{
    switch (nIDEvent)
    {
        case IDT_APPEARING:
            m_nAnimStatus=IDT_APPEARING;
            switch(m_nTaskbarPlacement)
            {
                case TASKBAR_ON_BOTTOM:
                    if (m_nCurrentPosY>(m_nStartPosY-m_nSkinHeight))
                        m_nCurrentPosY-=m_nIncrement;
                    else
                    {
                        KillTimer(IDT_APPEARING);
                        SetTimer(IDT_WAITING,m_dwTimeToLive,NULL);
                        m_nAnimStatus=IDT_WAITING;
                    }
                    break;
                case TASKBAR_ON_TOP:
                    if ((m_nCurrentPosY-m_nStartPosY)<m_nSkinHeight)
                        m_nCurrentPosY+=m_nIncrement;
                    else
                    {
                        KillTimer(IDT_APPEARING);
                        SetTimer(IDT_WAITING,m_dwTimeToLive,NULL);
                        m_nAnimStatus=IDT_WAITING;
                    }
                    break;
                case TASKBAR_ON_LEFT:
                    if ((m_nCurrentPosX-m_nStartPosX)<m_nSkinWidth)
                        m_nCurrentPosX+=m_nIncrement;
                    else
                    {
                        KillTimer(IDT_APPEARING);
                        SetTimer(IDT_WAITING,m_dwTimeToLive,NULL);
                        m_nAnimStatus=IDT_WAITING;
                    }
                    break;
                case TASKBAR_ON_RIGHT:
                    if (m_nCurrentPosX>(m_nStartPosX-m_nSkinWidth))
                        m_nCurrentPosX-=m_nIncrement;
                    else
                    {
                        KillTimer(IDT_APPEARING);
                        SetTimer(IDT_WAITING,m_dwTimeToLive,NULL);
                        m_nAnimStatus=IDT_WAITING;
                    }
                    break;
            }
            SetWindowPos(&wndTopMost,m_nCurrentPosX,m_nCurrentPosY,m_nSkinWidth,m_nSkinHeight,SWP_NOOWNERZORDER/* | SWP_NOZORDER*/ | SWP_NOACTIVATE);
            //RedrawWindow();
            break;

        case IDT_WAITING:
                  KillTimer(IDT_WAITING);
            SetTimer(IDT_DISAPPEARING,m_dwDelayBetweenHideEvents,NULL);
            break;

        case IDT_DISAPPEARING:
            m_nAnimStatus=IDT_DISAPPEARING;
            switch(m_nTaskbarPlacement)
            {
                case TASKBAR_ON_BOTTOM:
                    if (m_nCurrentPosY<m_nStartPosY)
                        m_nCurrentPosY+=m_nIncrement;
                    else
                    {
                        KillTimer(IDT_DISAPPEARING);
                        Hide();
                    }
                    break;
                case TASKBAR_ON_TOP:
                    if (m_nCurrentPosY>m_nStartPosY)
                        m_nCurrentPosY-=m_nIncrement;
                    else
                    {
                        KillTimer(IDT_DISAPPEARING);
                        Hide();
                    }
                    break;
                case TASKBAR_ON_LEFT:
                    if (m_nCurrentPosX>m_nStartPosX)
                        m_nCurrentPosX-=m_nIncrement;
                    else
                    {
                        KillTimer(IDT_DISAPPEARING);
                        Hide();
                    }
                    break;
                case TASKBAR_ON_RIGHT:
                    if (m_nCurrentPosX<m_nStartPosX)
                        m_nCurrentPosX+=m_nIncrement;
                    else
                    {
                        KillTimer(IDT_DISAPPEARING);
                        Hide();
                    }
                    break;
            }
            SetWindowPos(&wndTopMost,m_nCurrentPosX,m_nCurrentPosY,m_nSkinWidth,m_nSkinHeight,SWP_NOOWNERZORDER/* | SWP_NOZORDER*/ | SWP_NOACTIVATE);
            //RedrawWindow();
            break;
    }

    CWnd::OnTimer(nIDEvent);
}
 
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour November 2023 - January 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
User avatar
Silvio.Falconi
 
Posts: 6774
Joined: Thu Oct 18, 2012 7:17 pm

Re: Toast Alert vs (my) TdesktopAlert

Postby cnavarro » Sat Apr 02, 2016 11:50 am

Yes,
I saw also the example I built with Visual Studio
That's the ideal solution, but there is much work to convert Fivewin

https://code.msdn.microsoft.com/windows ... e-52eeba29
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6500
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Toast Alert vs (my) TdesktopAlert

Postby cnavarro » Sat Apr 02, 2016 4:11 pm

Any idea to get this look?
For with the TCalenda control it is not well
Or
Someone has a different calendar control or as set TCalenda with a size larger

Image
Image
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6500
Joined: Wed Feb 15, 2012 8:25 pm
Location: España


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: richard-service and 79 guests

cron