Desktop Alerts

Re: Desktop Alerts

Postby Silvio.Falconi » Tue Mar 08, 2016 1:15 pm

Antonio,
Add popupmenu into btndown
Add DesktopAlerts Settings dialog


Two question

1. when I click on btndown it open the DesktopAlerts Settings dialog but when the ntimer is finished it close this dialog and the final user cannot insert his options
any solution ?

2. How I can to have an animation i explain you
When it is showed the dialogAlert from downs to up and when it is ended the dialog hide to down




Code: Select all  Expand view

#include "FiveWin.ch"
#include "Slider.ch"







static nTransparency
static nlongTimer


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

    function Main()

       local oWnd

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

       ACTIVATE WINDOW oWnd ;
          ON CLICK DesktopAlert( oWnd )

    return nil

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

    function DesktopAlert( oWnd )

       local oDlg, oBrush, oFont
       local hLogo := FWLogoBitMap()
       local oBtnClose
       local oBtnDown
       local oFontBody



       DEFINE FONT oFont NAME "Verdana" BOLD
       DEFINE FONT oFontBody NAME "Verdana"  SIZE 0, -9
       DEFINE BRUSH oBrush GRADIENT { { 1, nRgb( 221, 236, 253 ), nRgb( 95, 131, 179 ) } }

       DEFINE DIALOG oDlg STYLE nOr( WS_POPUP, WS_BORDER ) BRUSH oBrush ;
          SIZE 328, 73

       @ 0.6, 6 SAY "A desktop notification" OF oDlg TRANSPARENT FONT oFont


       @ 1.2, 6 SAY "This a sample text area."+CRLF+"This a sample text area." OF oDlg;
                     TRANSPARENT FONT oFontBody SIZE 100,30



      @ 0.6, oDlg:nWidth-175 BTNBMP oBtnClose FILENAME "C:\Work\fwh\bitmaps\16x16\cancel.bmp" ;
      SIZE 10, 10 OF oDlg NOBORDER ACTION oDlg:End()

       @ 0.6, oDlg:nWidth-185 BTNBMP oBtnDown FILENAME "C:\Work\fwh\bitmaps\16x16\darrow.bmp" ;
      SIZE 10, 10 OF oDlg NOBORDER ACTION ShowPopup( oDlg )


       oBtnClose:ltransparent:=.t.
       oBtnDown:ltransparent:=.t.

       ACTIVATE DIALOG oDlg ;
          ON INIT ( SetTransparent( oDlg ), oDlg:Shadow(), BuildTimer( oDlg ) ) ;
          ON CLICK oDlg:End() ;
          ON PAINT DrawBitmap( hDC, hLogo, 9, 9 ) ;
          VALID ( DeleteObject( hLogo ), .T. ) ;
          NOWAIT

       oBrush:End()
       oFont:End()
       oWnd:SetFocus()

    return nil

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

    function BuildTimer( oDlg )

       local oTimer
       local nStart := Seconds()


       DEFAULT nlongTimer:= 5

       oDlg:SetPos( ScreenHeight() - 80, ScreenWidth( 0 ) - 350 )

       DEFINE TIMER oTimer OF oDlg ;
          INTERVAL 10;
          ACTION If( Seconds() - nStart > nlongTimer, oDlg:End(),)

       ACTIVATE TIMER oTimer

    return nil

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

    #define GWL_EXSTYLE   -20
    #define WS_EX_LAYERED 524288

static function SetTransparent( oDlg )

   DEFAULT nTransparency:= 180

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

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

    return nil

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

   static function DeskTopAlertSettings()
      Local oDlgSettings
      Local cText_Duration:="How long should the desktop alert appear ?"
      local cText_transparency:="How transparency should the desktop be ?"
      local oTrans,oDuration
      local obtn[3]
      local oGrp[2]
      LOCAL oSay[2]
      local nOptionDuration := 5
      local nOptionTrans:= 180
      Local nBottom   := 33
      Local nRight    := 62
    *  Local nWidth :=  Max( nRight * DLG_CHARPIX_W, 180 )
    *  Local nHeight := nBottom * DLG_CHARPIX_H




      DEFINE DIALOG oDlgSettings TITLE "DeskTopAlert Settings" SIZE 450, 300 ;
      STYLE nOr( WS_THICKFRAME, WS_SYSMENU )

      @ 0, 2 GROUP oGrp[1] PROMPT "Duration" OF oDlgSettings SIZE 200,40
      @ 4, 2 GROUP oGrp[2] PROMPT "Transparency" OF oDlgSettings SIZE 200,40
      @ 0.5, 6 SAY oSay[1] PROMPT cText_Duration OF oDlgSettings   SIZE 120,10
      @ 4.2, 6 SAY oSay[2] PROMPT cText_transparency OF oDlgSettings SIZE 120,10







     @ 22, 45 SLIDER oDuration VAR nOptionDuration OF oDlgSettings ;
               HORIZONTAL ;
               RIGHT DIRECTION ;
               RANGE -5, 60 ;
               MARKS 11;
               EXACT;  
               ON CHANGE  nlongTimer := nOptionDuration ;
               SIZE 102, 12 PIXEL



      @ 78, 45 SLIDER oTrans VAR nOptionTrans OF oDlgSettings ;
               HORIZONTAL ;
               RIGHT DIRECTION ;
               RANGE -10, 200 ;
               MARKS 11;
               EXACT;  
               ON CHANGE nTransparency := nOptionTrans ;
               SIZE 102, 12 PIXEL



     @ 113, 14 BUTTON obtn[1] PROMPT "&Preview" SIZE 45,12  OF oDlgSettings PIXEL
     @ 113, 94 BUTTON obtn[2] PROMPT "&Ok" SIZE 45,12  OF oDlgSettings PIXEL       action  oDlgSettings:End(IDOK)
     @ 113, 164 BUTTON obtn[3] PROMPT "&Cancel" SIZE 45,12  OF oDlgSettings PIXEL  action  oDlgSettings:End(IDCANCEL)
     ACTIVATE DIALOG oDlgSettings CENTERED



     IF oDlgSettings:nresult == IDOK

               msginfo(nTransparency,nlongTimer )
        Endif

      return nil


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

  function ShowPopup( oDlg )

   local oPopSample

    MENU oPopSample POPUP
    MENUITEM "Your Option"
   SEPARATOR
   MENUITEM "Desktop Alert Settimgs" ACTION DeskTopAlertSettings()
ENDMENU

   ACTIVATE POPUP oPopSample OF oDlg AT 100, 100

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: 6716
Joined: Thu Oct 18, 2012 7:17 pm

Re: Desktop Alerts

Postby James Bott » Tue Mar 08, 2016 3:06 pm

This notification alert is looking really nice!

I have been looking into information for the standard Window 10 notifications, that will also show up in the notification list. I think users are going to expect this.

I found some API information but only C++ code examples. Has anyone done any development on these notifications?

I expect we are going to need both types of notifications, FW's own type for older versions of Windows, and Win 8x/10 type for newer versions of Windows.

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Re: Desktop Alerts

Postby Antonio Linares » Tue Mar 08, 2016 10:22 pm

James,

I have been searching for ToastNotificationManager C++ examples and found some but couln't compile them without errors
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41205
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Desktop Alerts

Postby ukoenig » Tue Mar 08, 2016 10:38 pm

Silvio,

1. when I click on btndown it open the DesktopAlerts Settings dialog but when the ntimer is finished it close this dialog and the final user cannot insert his options
any solution ?


a extended sample.
Now You can open the popup without closing the message.
Testing backgrounds and open on button-action.

DOWNLOAD ( full sample )
http://www.pflegeplus.com/DOWNLOADS/Message2.zip

Image

best regards
Uwe :D
Since 1995 ( the first release of FW 1.9 )
i work with FW.
If you have any questions about special functions, maybe i can help.
User avatar
ukoenig
 
Posts: 4043
Joined: Wed Dec 19, 2007 6:40 pm
Location: Germany

Re: Desktop Alerts

Postby Silvio.Falconi » Wed Mar 09, 2016 10:02 am

Uwe give me error on

Progetto: test3, Ambiente: bcc7xHarbor:
[1]:Harbour.Exe test3.prg /m /n0 /gc1 /es2 /a /iC:\Work\fwh\include /iC:\work\XHARBOUR\Include /jC:\Work\Errori\DESKTO~1\I18n\Main.hil /iinclude;c:\work\fwh\include;C:\work\XHARBOUR\include /oObj\test3.c
xHarbour 1.2.3 Intl. (SimpLex) (Build 20150603)
Copyright 1999-2015, http://www.xharbour.org http://www.harbour-project.org/
Compiling 'test3.prg'...
Generating international list to 'C:\Work\Errori\DESKTO~1\I18n\Main.hil'...
test3.prg(83) Warning W0027 Meaningless use of expression: 'Numeric'

No code generated


Code: Select all  Expand view

#include "FiveWin.ch"
#include "Slider.ch"

static nTransparency




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

    function Main()

       local oWnd
       Local End := .F.

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

      * ACTIVATE WINDOW oWnd ;
       *   ON CLICK DesktopAlert( oWnd )
       ACTIVATE DIALOG oWnd ;
          ON CLICK IF( lEnd = .F., lEnd := DesktopAlert( oWnd, 3 ), )

    return nil

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




    function DesktopAlert( oWnd , nlongTimer)

       local oDlg, oBrush, oFont
       local hLogo := FWLogoBitMap()
       local oBtnClose
       local oBtnDown
       local oFontBody
       local lEnd := .T.


       DEFINE FONT oFont NAME "Verdana" BOLD
       DEFINE FONT oFontBody NAME "Verdana"  SIZE 0, -9
       DEFINE BRUSH oBrush GRADIENT { { 1, nRgb( 221, 236, 253 ), nRgb( 95, 131, 179 ) } }

       DEFINE DIALOG oDlg STYLE nOr( WS_POPUP, WS_BORDER ) BRUSH oBrush ;
          SIZE 328, 73

       @ 0.6, 6 SAY "A desktop notification" OF oDlg TRANSPARENT FONT oFont


       @ 1.2, 6 SAY "This a sample text area."+CRLF+"This a sample text area." OF oDlg;
                     TRANSPARENT FONT oFontBody SIZE 100,30



      @ 0.6, oDlg:nWidth-175 BTNBMP oBtnClose FILENAME "C:\Work\fwh\bitmaps\16x16\cancel.bmp" ;
      SIZE 10, 10 OF oDlg NOBORDER ACTION oDlg:End()

       @ 0.6, oDlg:nWidth-185 BTNBMP oBtnDown FILENAME "C:\Work\fwh\bitmaps\16x16\darrow.bmp" ;
      SIZE 10, 10 OF oDlg NOBORDER ACTION ShowPopup( oDlg )


       oBtnClose:ltransparent:=.t.
       oBtnDown:ltransparent:=.t.








ACTIVATE DIALOG oDlg ;
ON INIT ( SetTransparent( oDlg ), oDlg:Shadow(), oDlg:Move( 70, 70, , , .T.) ) ;
ON CLICK oDlg:End() ;
ON PAINT DrawBitmap( hDC, hLogo, 9, 9 ) ;
VALID ( nlongTimer > 0, .T. ) ;
NOWAIT




IF nlongTimer > 0
   SYSWAIT1(nlongTimer)
   lEnd := .F.
   oDlg:End()
ENDIF



DeleteObject( hLogo )
oBrush:End()
oFont:End()
oWnd:SetFocus()


RETURN lEnd


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

 static FUNCTION SYSWAIT1( nLong )
local nSeconds

DEFAULT nLong := .1
nSeconds := Seconds() + nLong

WHILE Seconds() < nSeconds
   SysRefresh()
END

RETURN NIL
   //----------------------------------------------------------------------------//



    function BuildTimer( oDlg )

       local oTimer
       local nStart := Seconds()


       DEFAULT nlongTimer:= 5

       oDlg:SetPos( ScreenHeight() - 80, ScreenWidth( 0 ) - 350 )

       DEFINE TIMER oTimer OF oDlg ;
          INTERVAL 10;
          ACTION If( Seconds() - nStart > nlongTimer, oDlg:End(),)

       ACTIVATE TIMER oTimer

    return nil

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

    #define GWL_EXSTYLE   -20
    #define WS_EX_LAYERED 524288

static function SetTransparent( oDlg )

   DEFAULT nTransparency:= 180

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

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

    return nil

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

   static function DeskTopAlertSettings()
      Local oDlgSettings
      Local cText_Duration:="How long should the desktop alert appear ?"
      local cText_transparency:="How transparency should the desktop be ?"
      local oTrans,oDuration
      local obtn[3]
      local oGrp[2]
      LOCAL oSay[2]
      local nOptionDuration := 5
      local nOptionTrans:= 180
      Local nBottom   := 33
      Local nRight    := 62
    *  Local nWidth :=  Max( nRight * DLG_CHARPIX_W, 180 )
    *  Local nHeight := nBottom * DLG_CHARPIX_H




      DEFINE DIALOG oDlgSettings TITLE "DeskTopAlert Settings" SIZE 450, 300 ;
      STYLE nOr( WS_THICKFRAME, WS_SYSMENU )

      @ 0, 2 GROUP oGrp[1] PROMPT "Duration" OF oDlgSettings SIZE 200,40
      @ 4, 2 GROUP oGrp[2] PROMPT "Transparency" OF oDlgSettings SIZE 200,40
      @ 0.5, 6 SAY oSay[1] PROMPT cText_Duration OF oDlgSettings   SIZE 120,10
      @ 4.2, 6 SAY oSay[2] PROMPT cText_transparency OF oDlgSettings SIZE 120,10







     @ 22, 45 SLIDER oDuration VAR nOptionDuration OF oDlgSettings ;
               HORIZONTAL ;
               RIGHT DIRECTION ;
               RANGE -5, 60 ;
               MARKS 11;
               EXACT;
               ON CHANGE  nlongTimer := nOptionDuration ;
               SIZE 102, 12 PIXEL



      @ 78, 45 SLIDER oTrans VAR nOptionTrans OF oDlgSettings ;
               HORIZONTAL ;
               RIGHT DIRECTION ;
               RANGE -10, 200 ;
               MARKS 11;
               EXACT;
               ON CHANGE nTransparency := nOptionTrans ;
               SIZE 102, 12 PIXEL



     @ 113, 14 BUTTON obtn[1] PROMPT "&Preview" SIZE 45,12  OF oDlgSettings PIXEL
     @ 113, 94 BUTTON obtn[2] PROMPT "&Ok" SIZE 45,12  OF oDlgSettings PIXEL       action  oDlgSettings:End(IDOK)
     @ 113, 164 BUTTON obtn[3] PROMPT "&Cancel" SIZE 45,12  OF oDlgSettings PIXEL  action  oDlgSettings:End(IDCANCEL)
     ACTIVATE DIALOG oDlgSettings CENTERED



     IF oDlgSettings:nresult == IDOK

               msginfo(nTransparency,nlongTimer )
        Endif

      return nil


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

  function ShowPopup( oDlg )

   local oPopSample

    MENU oPopSample POPUP
    MENUITEM "Your Option"
   SEPARATOR
   MENUITEM "Desktop Alert Settimgs" ACTION DeskTopAlertSettings()
ENDMENU

   ACTIVATE POPUP oPopSample OF oDlg AT 100, 100

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: 6716
Joined: Thu Oct 18, 2012 7:17 pm

Re: Desktop Alerts

Postby Silvio.Falconi » Wed Mar 09, 2016 10:13 am

Antonio Linares wrote:James,

I have been searching for ToastNotificationManager C++ examples and found some but couln't compile them without errors



I found this
>DesktopAlert
https://documentation.devexpress.com/#WindowsForms/CustomDocument5395

or
>toast manager
https://documentation.devexpress.com/#WindowsForms/CustomDocument17020
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: 6716
Joined: Thu Oct 18, 2012 7:17 pm

Re: Desktop Alerts

Postby ukoenig » Wed Mar 09, 2016 1:18 pm

Silvio,

the needed changes using Your original code
Don't use a timer !!! nLongTimer = defined seconds

Code: Select all  Expand view

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

STATIC nTransparency, lEnd := .F., nLongTimer := 3

function Main()
local oWnd  

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

ACTIVATE WINDOW oWnd ;
ON CLICK IF( lEnd = .F., DesktopAlert( oWnd, nlongTimer ), ) // only 1 instance permitted

return nil

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

function DesktopAlert( oWnd, nlongTimer )
local oDlg, oBrush, oFont
local hLogo := FWLogoBitMap()
local oBtnClose
local oBtnDown
local oFontBody

lEnd := .T.

DEFINE FONT oFont NAME "Verdana" BOLD
DEFINE FONT oFontBody NAME "Verdana"  SIZE 0, -9
DEFINE BRUSH oBrush GRADIENT { { 1, nRgb( 221, 236, 253 ), nRgb( 95, 131, 179 ) } }

DEFINE DIALOG oDlg STYLE nOr( WS_POPUP, WS_BORDER ) BRUSH oBrush ;
SIZE 328, 73

@ 0.6, 6 SAY "A desktop notification" OF oDlg TRANSPARENT FONT oFont

@ 1.2, 6 SAY "This a sample text area."+CRLF+"This a sample text area." OF oDlg;
TRANSPARENT FONT oFontBody SIZE 100,30

@ 0.6, oDlg:nWidth-175 BTNBMP oBtnClose FILENAME "C:\Work\fwh\bitmaps\16x16\cancel.bmp" ;
SIZE 10, 10 OF oDlg NOBORDER ACTION oDlg:End()

@ 0.6, oDlg:nWidth-185 BTNBMP oBtnDown FILENAME "C:\Work\fwh\bitmaps\16x16\darrow.bmp" ;
SIZE 10, 10 OF oDlg NOBORDER ACTION ShowPopup( oDlg )

oBtnClose:ltransparent:=.t.
oBtnDown:ltransparent:=.t.

ACTIVATE DIALOG oDlg ;
ON INIT ( SetTransparent( oDlg ), oDlg:Shadow() ) ;
ON CLICK oDlg:End() ;
ON PAINT DrawBitmap( hDC, hLogo, 9, 9 ) ;
VALID ( DeleteObject( hLogo ), .T. ) ;
NOWAIT

IF nlongTimer > 0
    SYSWAIT1(nlongTimer)
    lEnd := .F.
    oDlg:End()
ENDIF

oBrush:End()
oFont:End()
oWnd:SetFocus()

return  nil

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

#define GWL_EXSTYLE   -20
#define WS_EX_LAYERED 524288

static function SetTransparent( oDlg )

DEFAULT nTransparency:= 180

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

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

return nil

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

static function DeskTopAlertSettings()
Local oDlgSettings
Local cText_Duration:="How long should the desktop alert appear ?"
local cText_transparency:="How transparency should the desktop be ?"
local oTrans,oDuration
local obtn[3]
local oGrp[2]
LOCAL oSay[2]
local nOptionDuration := nlongTimer
local nOptionTrans:= 180
Local nBottom   := 33
Local nRight    := 62
    *  Local nWidth :=  Max( nRight * DLG_CHARPIX_W, 180 )
    *  Local nHeight := nBottom * DLG_CHARPIX_H

DEFINE DIALOG oDlgSettings TITLE "DeskTopAlert Settings" SIZE 450, 300 ;
STYLE nOr( WS_THICKFRAME, WS_SYSMENU )

@ 0, 2 GROUP oGrp[1] PROMPT "Duration ( 0 - 5 seconds )" OF oDlgSettings SIZE 200,40
@ 4, 2 GROUP oGrp[2] PROMPT "Transparency" OF oDlgSettings SIZE 200,40
@ 0.5, 6 SAY oSay[1] PROMPT cText_Duration OF oDlgSettings   SIZE 120,10
@ 4.2, 6 SAY oSay[2] PROMPT cText_transparency OF oDlgSettings SIZE 120,10

@ 22, 45 SLIDER oDuration VAR nOptionDuration OF oDlgSettings ;
               HORIZONTAL ;
               RIGHT DIRECTION ;
               RANGE 0, 5 ;  // 0 = NO close
               MARKS 6;
               EXACT;  
               ON CHANGE  nlongTimer := nOptionDuration ;
               SIZE 102, 12 PIXEL

@ 78, 45 SLIDER oTrans VAR nOptionTrans OF oDlgSettings ;
               HORIZONTAL ;
               RIGHT DIRECTION ;
               RANGE -10, 200 ;
               MARKS 11;
               EXACT;  
               ON CHANGE nTransparency := nOptionTrans ;
               SIZE 102, 12 PIXEL

@ 113, 14 BUTTON obtn[1] PROMPT "&Preview" SIZE 45,12  OF oDlgSettings PIXEL
@ 113, 94 BUTTON obtn[2] PROMPT "&Ok" SIZE 45,12  OF oDlgSettings PIXEL       action  oDlgSettings:End(IDOK)
@ 113, 164 BUTTON obtn[3] PROMPT "&Cancel" SIZE 45,12  OF oDlgSettings PIXEL  action  oDlgSettings:End(IDCANCEL)
ACTIVATE DIALOG oDlgSettings CENTERED

IF oDlgSettings:nresult == IDOK
               msginfo( "Transp. : " + STR( nTransparency), "Seconds : " + STR( nlongTimer ) )
Endif

return nil

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

function ShowPopup( oDlg )
local oPopSample

MENU oPopSample POPUP
    MENUITEM "Your Option"
   SEPARATOR
   MENUITEM "Desktop Alert Settimgs" ACTION DeskTopAlertSettings()
ENDMENU

ACTIVATE POPUP oPopSample OF oDlg AT 100, 100

return nil

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

static FUNCTION SYSWAIT1( nLong )
local nSeconds

DEFAULT nLong := .1
nSeconds := Seconds() + nLong

WHILE Seconds() < nSeconds
   SysRefresh()
END

RETURN NIL
 


best regards
Uwe :D
Since 1995 ( the first release of FW 1.9 )
i work with FW.
If you have any questions about special functions, maybe i can help.
User avatar
ukoenig
 
Posts: 4043
Joined: Wed Dec 19, 2007 6:40 pm
Location: Germany

Re: Desktop Alerts

Postby cnavarro » Wed Mar 09, 2016 11:27 pm

James Bott wrote:This notification alert is looking really nice!

I expect we are going to need both types of notifications, FW's own type for older versions of Windows, and Win 8x/10 type for newer versions of Windows.

James


Something like this?
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: 6498
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Desktop Alerts

Postby TimStone » Wed Mar 09, 2016 11:56 pm

Notifications actually will auto generate within the program so we don't need a click control. The samples Antonio put up are nicely consistent with what Windows 8 / 10 provides.

The one thing that will be a great help is if we can send the notifications to be saved in the notification center. Thus people can quickly review them if they want. This will be in the Win 10 API.
Tim Stone
http://www.MasterLinkSoftware.com
http://www.autoshopwriter.com
timstone@masterlinksoftware.com
Using: FWH 23.10 with Harbour 3.2.0 / Microsoft Visual Studio Community 2022-24 32/64 bit
User avatar
TimStone
 
Posts: 2897
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA

Re: Desktop Alerts

Postby Silvio.Falconi » Thu Mar 10, 2016 8:14 am

Uwe,
yes now run But I need show the dialog on this position

oDlgSettings:SetPos( ScreenHeight() - 80, ScreenWidth( 0 ) - 350 )
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: 6716
Joined: Thu Oct 18, 2012 7:17 pm

Re: Desktop Alerts

Postby Silvio.Falconi » Thu Mar 10, 2016 11:37 am

I made a test
I add two buttons Close and down
But I not Know How give to button close the end() action and to button down the menupopup action
I made two aItems one for the btnclose and one for btndown
each item have an array type {name, .f.,{0,0,0,0}}


Image


I use Marlet font to create btnclose and btndown buttons.

I used the array aItems add for a example we can add other buttons and other baction in future

when the button close it created with the METHOD BtnClose( hDC,nTop,nLeft ) it set the array ::aItems[1,3] := ::aBtnClose
the same for the button btndown (METHOD BtnDown( hDC,nTop,nLeft ) -> ::aItems[2,3] := ::aBtndown )
when I move the mouse over the buttons I can show a msginfo but I not Know how assign the baction
please see the mousemove and LButtonUp to correct it


Code: Select all  Expand view

#include "fivewin.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, 250, 150, oWnd, .T., CLR_CYAN, CLR_WHITE )

   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.

   // These are not working yet
   oAlert:lBtnClose   = .T.
   oAlert:lBtnDown    = .T.
   oAlert:lSplitHdr   = .T.


return nil




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

CLASS TDesktopAlert FROM TWindow  //from c5Tooltip

      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 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





      METHOD New( nTop, nLeft, nWidth, nHeight, oWnd, lDisenio, nClrPane, ;
                  nClrPane2, nClrText, nWRadio, nHRadio,aItems) 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 )



ENDCLASS

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

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

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


   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


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

    ::aCoors       := {}



   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( .T. )

   SetTransparent( self )


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() - 160, ScreenWidth( 0 ) - 350 )

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

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

   DeleteObject( ::hRgn )

return 0

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

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

  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, ::lOverClose )
   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, ::lOverClose )
::aItems[2,3] := ::aBtndown
return 0

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


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

    METHOD MouseMove  ( nRow, nCol, nFlags ) CLASS TDesktopAlert

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


for n := 1 to nLen
    if PtInRect( nRow, nCol, ::aBtnClose )
       lFind := .t.
       ::nOver := n
       if nOver != n
          //::Refresh(.f.)
       endif
       exit
    endif
next

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



if lFind
   if ::lOverClose
      CursorHand()
   else
      CursorArrow()
   endif


       Msginfo( ::aItems[::nOver,1]  , (::aItems[::nOver,2]))


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 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










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

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 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], "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 )

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

       SetLayeredWindowAttributes( oDlg:hWnd, 0, 180, 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: 6716
Joined: Thu Oct 18, 2012 7:17 pm

Re: Desktop Alerts

Postby Antonio Linares » Thu Mar 10, 2016 4:55 pm

Silvio,

This seems to work fine:
Code: Select all  Expand view
METHOD LButtonDown( nRow, nCol, nFlags ) CLASS TDesktopAlert

    if ::lOverClose
       ::End()
    endif  

return 0
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41205
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Desktop Alerts

Postby Silvio.Falconi » Thu Mar 10, 2016 5:40 pm

Antonio,thanks now for the btnclose run ok it close thedesktop Alert

for the btnDown it run I can click on it but I not Know how open a popup menu



New code with new modifies

add loverDown see MouseMove method and LButtonDown
I add popmenu method

Code: Select all  Expand view

 
#include "fivewin.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, 250, 150, oWnd, .T., CLR_CYAN, CLR_WHITE )

   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.

   // These are not working yet
   oAlert:lBtnClose   = .T.
   oAlert:lBtnDown    = .T.
   oAlert:lSplitHdr   = .T.


return nil




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

CLASS TDesktopAlert FROM TWindow  //from c5Tooltip

      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





      METHOD New( nTop, nLeft, nWidth, nHeight, oWnd, lDisenio, nClrPane, ;
                  nClrPane2, nClrText, nWRadio, nHRadio,aItems) 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


ENDCLASS

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

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

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


   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


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

    ::aCoors       := {}



   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( .T. )

   SetTransparent( self )


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() - 160, ScreenWidth( 0 ) - 350 )

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

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

   DeleteObject( ::hRgn )

return 0

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

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

  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
            ::bLCliCked := {| nRow, nCol, nKey | ::PopMenu( nRow, nCol, nKey ) }
      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

    MENU oPopUp POPUP
      MENU
          MENUITEM "Your Option"
           SEPARATOR
          MENUITEM "Desktop Alert Settimgs" ACTION NIL // 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










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

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 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], "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 )

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

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

    return nil



 



I tried to insert

Code: Select all  Expand view
METHOD LButtonDown( nRow, nCol, nFlags ) CLASS TDesktopAlert

    if ::lOverClose
       ::End()
    endif

       if ::lOverDown

           ::bRClicked := {| nRow, nCol, nKey | ::PopMenu( nRow, nCol, nKey ) }

              if ::bRClicked != nil
                        Eval( ::bRClicked, nRow, nCol, nFlags, Self )
             endif


      endif



    return 0

 


but not run ok any solution pls ?
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: 6716
Joined: Thu Oct 18, 2012 7:17 pm

Re: Desktop Alerts

Postby Antonio Linares » Thu Mar 10, 2016 6:45 pm

Silvio,

With these changes it is working fine:

Code: Select all  Expand view
METHOD LButtonDown( nRow, nCol, nFlags ) CLASS TDesktopAlert

    if ::lOverClose
       ::End()
    endif

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

    return 0


Code: Select all  Expand view
METHOD PopMenu( nRow, nCol, nKey ) CLASS TDesktopAlert
   LOCAL oPopup

    MENU oPopUp POPUP
       MENUITEM "Your Option" ACTION MsgInfo( "first" )
       SEPARATOR
       MENUITEM "Desktop Alert Settimgs" ACTION MsgInfo( "second" ) // DeskTopAlertSettings()
   ENDMENU

   ACTIVATE POPUP oPopup OF Self AT nRow, nCol

return nil
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41205
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Desktop Alerts

Postby Silvio.Falconi » Thu Mar 10, 2016 7:04 pm

Antonio thanks !!!

Now I go to make DesktopAlertSettings method


New code ( with Antonio modifies)
Code: Select all  Expand view

#include "fivewin.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, 250, 250, oWnd, .T., CLR_HRED, CLR_WHITE )

   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.

   // These are not working yet
   oAlert:lBtnClose   = .T.
   oAlert:lBtnDown    = .T.
   oAlert:lSplitHdr   = .T.


return nil




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

CLASS TDesktopAlert FROM TWindow  //from c5Tooltip

      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



      METHOD New( nTop, nLeft, nWidth, nHeight, oWnd, lDisenio, nClrPane, ;
                  nClrPane2, nClrText, nWRadio, nHRadio,aItems) 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

ENDCLASS

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

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

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


   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     = 180  //trasparency

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




   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( .T. )


   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 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

  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

    MENU oPopUp POPUP
       MENUITEM "Your Option" ACTION MsgInfo( "first" )
       SEPARATOR
       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



    Msginfo("settings")


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 := 180

       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: 6716
Joined: Thu Oct 18, 2012 7:17 pm

PreviousNext

Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: MarcoBoschi and 12 guests