Desktop Alerts

User avatar
Silvio.Falconi
Posts: 7142
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Desktop Alerts

Post by Silvio.Falconi »

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

#include "FiveWin.ch"#include "Slider.ch"static nTransparencystatic 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 524288static 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, 100return nil 
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour March-April 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
James Bott
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Re: Desktop Alerts

Post by James Bott »

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
Antonio Linares
Site Admin
Posts: 42561
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 36 times
Been thanked: 81 times
Contact:

Re: Desktop Alerts

Post by Antonio Linares »

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
ukoenig
Posts: 4043
Joined: Wed Dec 19, 2007 6:40 pm
Location: Germany
Contact:

Re: Desktop Alerts

Post by ukoenig »

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
Silvio.Falconi
Posts: 7142
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Desktop Alerts

Post by Silvio.Falconi »

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

#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. ) ;NOWAITIF nlongTimer > 0   SYSWAIT1(nlongTimer)   lEnd := .F.   oDlg:End()ENDIFDeleteObject( hLogo )oBrush:End()oFont:End()oWnd:SetFocus()RETURN lEnd   //----------------------------------------------------------------------------// static FUNCTION SYSWAIT1( nLong )local nSecondsDEFAULT nLong := .1nSeconds := Seconds() + nLongWHILE Seconds() < nSeconds   SysRefresh()ENDRETURN 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 524288static 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, 100return nil 
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)
I use : FiveWin for Harbour March-April 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: 7142
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Desktop Alerts

Post by Silvio.Falconi »

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 March-April 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
ukoenig
Posts: 4043
Joined: Wed Dec 19, 2007 6:40 pm
Location: Germany
Contact:

Re: Desktop Alerts

Post by ukoenig »

Silvio,

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

Code: Select all | Expand

#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 permittedreturn nil//---------------------------------function DesktopAlert( oWnd, nlongTimer )local oDlg, oBrush, oFontlocal hLogo := FWLogoBitMap()local oBtnCloselocal oBtnDownlocal oFontBodylEnd := .T.DEFINE FONT oFont NAME "Verdana" BOLDDEFINE FONT oFontBody NAME "Verdana"  SIZE 0, -9DEFINE 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. ) ;NOWAITIF nlongTimer > 0    SYSWAIT1(nlongTimer)    lEnd := .F.    oDlg:End()ENDIFoBrush:End()oFont:End()oWnd:SetFocus()return  nil//------------------------------------#define GWL_EXSTYLE   -20#define WS_EX_LAYERED 524288static function SetTransparent( oDlg )DEFAULT nTransparency:= 180SetWindowLong( 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 oDlgSettingsLocal cText_Duration:="How long should the desktop alert appear ?"local cText_transparency:="How transparency should the desktop be ?"local oTrans,oDurationlocal obtn[3]local oGrp[2]LOCAL oSay[2]local nOptionDuration := nlongTimerlocal nOptionTrans:= 180Local nBottom   := 33Local nRight    := 62    *  Local nWidth :=  Max( nRight * DLG_CHARPIX_W, 180 )    *  Local nHeight := nBottom * DLG_CHARPIX_HDEFINE 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 CENTEREDIF oDlgSettings:nresult == IDOK               msginfo( "Transp. : " + STR( nTransparency), "Seconds : " + STR( nlongTimer ) )Endifreturn nil //-----------------------------function ShowPopup( oDlg )local oPopSampleMENU oPopSample POPUP    MENUITEM "Your Option"   SEPARATOR   MENUITEM "Desktop Alert Settimgs" ACTION DeskTopAlertSettings()ENDMENUACTIVATE POPUP oPopSample OF oDlg AT 100, 100return nil//-------------------------------static FUNCTION SYSWAIT1( nLong )local nSecondsDEFAULT nLong := .1nSeconds := Seconds() + nLongWHILE Seconds() < nSeconds   SysRefresh()ENDRETURN 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
cnavarro
Posts: 6558
Joined: Wed Feb 15, 2012 8:25 pm
Location: España
Been thanked: 3 times

Re: Desktop Alerts

Post by cnavarro »

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
TimStone
Posts: 2955
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA
Has thanked: 25 times
Been thanked: 2 times
Contact:

Re: Desktop Alerts

Post by TimStone »

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
Silvio.Falconi
Posts: 7142
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Desktop Alerts

Post by Silvio.Falconi »

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 March-April 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: 7142
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Desktop Alerts

Post by Silvio.Falconi »

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

#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 := selfDEFAULT 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   endifreturn ::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]}   endifreturn 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 )  endifreturn 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 )   endifreturn 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 0METHOD 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] := ::aBtndownreturn 0//----------------------------------------------------------------------------// METHOD LButtonDown( nRow, nCol, nFlags ) CLASS TDesktopAlertreturn 0//----------------------------------------------------------------------------//    METHOD MouseMove  ( nRow, nCol, nFlags ) CLASS TDesktopAlertlocal nOver := ::nOverlocal nlocal 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    endifnext::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()endifif nOver != ::nOver   ::Refresh(.f.)endifreturn 0//----------------------------------------------------------------------------//    METHOD LButtonUp  ( nRow, nCol, nFlags ) CLASS TDesktopAlertif ::nOver > 0   if ::lOverClose      ::aItems[1,2] := .t.   else      ::nOption := ::nOver      if ::bAction != nil         eval(::bAction, ::nOption, ::aItems[::nOption,1])      endif   endif   ::Refresh()endifreturn 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    endifreturn 0//----------------------------------------------------------------------------//  METHOD GetItems() CLASS TDesktopAlertlocal nlocal nLen := len(::aItems)local aItems := {}for n := 1 to nLen    if ::aItems[n,2]       aadd(aItems, ::aItems[n,1] )    endifnextreturn 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, hOldFontlocal aRectlocal nMode// create a X buttonDEFAULT 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, hOldFontlocal aRectlocal nMode// create a X buttonDEFAULT 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 March-April 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
Antonio Linares
Site Admin
Posts: 42561
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 36 times
Been thanked: 81 times
Contact:

Re: Desktop Alerts

Post by Antonio Linares »

Silvio,

This seems to work fine:

Code: Select all | Expand

 METHOD LButtonDown( nRow, nCol, nFlags ) CLASS TDesktopAlert    if ::lOverClose       ::End()    endif   return 0
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Silvio.Falconi
Posts: 7142
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Desktop Alerts

Post by Silvio.Falconi »

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

 #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 optionsENDCLASS//----------------------------------------------------------------------------//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 := selfDEFAULT 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   endifreturn ::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]}   endifreturn 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 )  endifreturn 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 )   endifreturn 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 0METHOD 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] := ::aBtndownreturn 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 TDesktopAlertlocal nOver := ::nOverlocal nlocal 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    endifnext::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()   endifelse   ::nOver := -1   CursorArrow()endifif nOver != ::nOver   ::Refresh(.f.)endifreturn 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, nColreturn 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    endifreturn 0//----------------------------------------------------------------------------//  METHOD GetItems() CLASS TDesktopAlertlocal nlocal nLen := len(::aItems)local aItems := {}for n := 1 to nLen    if ::aItems[n,2]       aadd(aItems, ::aItems[n,1] )    endifnextreturn 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, hOldFontlocal aRectlocal nMode// create a X buttonDEFAULT 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, hOldFontlocal aRectlocal nMode// create a X buttonDEFAULT 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

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 March-April 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
Antonio Linares
Site Admin
Posts: 42561
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Has thanked: 36 times
Been thanked: 81 times
Contact:

Re: Desktop Alerts

Post by Antonio Linares »

Silvio,

With these changes it is working fine:

Code: Select all | Expand

 METHOD LButtonDown( nRow, nCol, nFlags ) CLASS TDesktopAlert    if ::lOverClose       ::End()    endif      if ::lOverDown            ::PopMenu( nRow, nCol, nFlags )      endif    return 0


Code: Select all | Expand

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, nColreturn nil
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Silvio.Falconi
Posts: 7142
Joined: Thu Oct 18, 2012 7:17 pm
Been thanked: 1 time

Re: Desktop Alerts

Post by Silvio.Falconi »

Antonio thanks !!!

Now I go to make DesktopAlertSettings method


New code ( with Antonio modifies)

Code: Select all | Expand

 #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 DesktopAlertSettingsENDCLASS//----------------------------------------------------------------------------//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 := selfDEFAULT 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   endifreturn ::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]}   endifreturn 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 )  endifreturn 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 )   endifreturn 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] := ::aBtndownreturn 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 TDesktopAlertlocal nOver := ::nOverlocal nlocal 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    endifnext::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()   endifelse   ::nOver := -1   CursorArrow()endifif nOver != ::nOver   ::Refresh(.f.)endifreturn 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, nColreturn 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    endifreturn 0//----------------------------------------------------------------------------//  METHOD GetItems() CLASS TDesktopAlertlocal nlocal nLen := len(::aItems)local aItems := {}for n := 1 to nLen    if ::aItems[n,2]       aadd(aItems, ::aItems[n,1] )    endifnextreturn 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, hOldFontlocal aRectlocal nMode// create a  arrow down buttonDEFAULT 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, hOldFontlocal aRectlocal nMode// create a X buttonDEFAULT 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 524288static 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 March-April 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
Post Reply