FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour how to get "Userdef" EVENT for ACTION
Posts: 1772
Joined: Thu Sep 05, 2019 05:32 AM
how to get "Userdef" EVENT for ACTION
Posted: Tue Mar 28, 2023 10:07 AM
hi,

i can call "find/replace" Dialod this Way
Code (fw): Select all Collapse
   FindReplaceDlg ( NIL, lNoUpDown, lNoMatchCase, lNoWholeWord, lCheckDown, lCheckMatchCase, lCheckWholeWord, cFind, cReplace, .T., cTitle )
now i need to receive Event
Code (fw): Select all Collapse
   _HMG_MsgIDFindDlg := REGISTERFINDMSGSTRING ()   // ADD

   case nMsg == _HMG_MsgIDFindDlg   // FindReplace Dialog Notification   ( by Dr. Claudio Soto, January 2014 )
         EVAL ( _HMG_FindReplaceOnAction )
but how to add Event to Fivewin :?:

---
Code (fw): Select all Collapse
static TCHAR       cFindWhat[ 1024 ];
static TCHAR       cReplaceWith[ 1024 ];
static FINDREPLACE FindReplace;
static HWND        hDlgFindReplace = NULL;

HB_FUNC( REGISTERFINDMSGSTRING )
{
   UINT MessageID = RegisterWindowMessage( FINDMSGSTRING );

   hb_retnl( ( LONG ) MessageID );
}

HB_FUNC( FINDREPLACEDLG )
{
   HWND hWnd           = HB_ISNIL( 1 ) ? GetActiveWindow() : ( HWND ) hb_parnl( 1 );
   BOOL NoUpDown       = ( BOOL ) ( HB_ISNIL( 2 ) ? FALSE : hb_parl( 2 ) );
   BOOL NoMatchCase    = ( BOOL ) ( HB_ISNIL( 3 ) ? FALSE : hb_parl( 3 ) );
   BOOL NoWholeWord    = ( BOOL ) ( HB_ISNIL( 4 ) ? FALSE : hb_parl( 4 ) );
   BOOL CheckDown      = ( BOOL ) ( HB_ISNIL( 5 ) ? TRUE  : hb_parl( 5 ) );
   BOOL CheckMatchCase = ( BOOL ) ( HB_ISNIL( 6 ) ? FALSE : hb_parl( 6 ) );
   BOOL CheckWholeWord = ( BOOL ) ( HB_ISNIL( 7 ) ? FALSE : hb_parl( 7 ) );
   BOOL lReplace       = ( BOOL ) hb_parl( 10 );

#ifndef UNICODE
   LPSTR FindWhat    = ( LPSTR ) hb_parc( 8 );
   LPSTR ReplaceWith = ( LPSTR ) hb_parc( 9 );
   LPSTR cTitle      = ( LPSTR ) hb_parc( 11 );
#else
   LPWSTR FindWhat    = AnsiToWide( ( char * ) hb_parc( 8 ) );
   LPWSTR ReplaceWith = AnsiToWide( ( char * ) hb_parc( 9 ) );
   LPWSTR cTitle      = AnsiToWide( ( char * ) hb_parc( 11 ) );
#endif

   if( hDlgFindReplace == NULL )
   {
      ZeroMemory( &FindReplace, sizeof( FindReplace ) );

      lstrcpy( cFindWhat, FindWhat );
      lstrcpy( cReplaceWith, ReplaceWith );

      FindReplace.lStructSize = sizeof( FindReplace );
      FindReplace.Flags       = ( NoUpDown  ? FR_HIDEUPDOWN : 0 ) | ( NoMatchCase    ? FR_HIDEMATCHCASE : 0 ) | ( NoWholeWord    ? FR_HIDEWHOLEWORD : 0 )
                                | ( CheckDown ? FR_DOWN : 0 ) | ( CheckMatchCase ? FR_MATCHCASE : 0 ) | ( CheckWholeWord ? FR_WHOLEWORD : 0 );
      FindReplace.hwndOwner        = hWnd;
      FindReplace.lpstrFindWhat    = cFindWhat;
      FindReplace.wFindWhatLen     = sizeof( cFindWhat ) / sizeof( TCHAR );
      FindReplace.lpstrReplaceWith = cReplaceWith;
      FindReplace.wReplaceWithLen  = sizeof( cReplaceWith ) / sizeof( TCHAR );

      if( lReplace )
         hDlgFindReplace = ReplaceText( &FindReplace );
      else
         hDlgFindReplace = FindText( &FindReplace );

      if( HB_ISCHAR( 11 ) )
         SetWindowText( hDlgFindReplace, cTitle );

      ShowWindow( hDlgFindReplace, SW_SHOW );
   }

#ifdef UNICODE
   hb_xfree( ( TCHAR * ) FindWhat );
   hb_xfree( ( TCHAR * ) ReplaceWith );
   hb_xfree( ( TCHAR * ) cTitle );
#endif
}
greeting,

Jimmy
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: how to get "Userdef" EVENT for ACTION
Posted: Tue Mar 28, 2023 10:31 AM

Dear Jimmy,

Is the event sent to hwndOwner ?

If so, then you need to inherit a class from TWindow and redefine HandleEvent() method and add support for such event

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 1772
Joined: Thu Sep 05, 2019 05:32 AM
Re: how to get "Userdef" EVENT for ACTION
Posted: Tue Mar 28, 2023 02:50 PM
hi Antonio,
Antonio Linares wrote:Is the event sent to hwndOwner ?
i´m not sure ... it is like other "Common Dialog"

it have to do with FINDREPLACE A/W structure
https://learn.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-findreplacea

there is HB_FUNC( FINDTEXT ) in c:\fwh\source\winapi\findtext.c but no HB:FUNC() for "replace"

i have take HB_FUNC( FINDREPLACEDLG ) from HMG and modify it for Fivewin ( Parameter Type )

as both work with same FINDREPLACE Structure it must be same Way for ACTION ... but how under Fivewin :?:
Antonio Linares wrote: If so, then you need to inherit a class from TWindow and redefine HandleEvent() method and add support for such event
have found CLASS TDlgFind() which use HB_FUNC( FINDTEXT )
Code (fw): Select all Collapse
   REDEFINE BUTTON ID IDOK OF Self ;
it "this" the "OK" Button from "Dialog" :?:

what do i need for "these" Buttons when using
Code (fw): Select all Collapse
  FindReplaceDlg ( NIL, lNoUpDown, lNoMatchCase, lNoWholeWord, lCheckDown, lCheckMatchCase, lCheckWholeWord, cFind, cReplace, .T., cTitle )


---
this is HMG CODE Syntax
Code (fw): Select all Collapse
#xtranslate FINDTEXTDIALOG  ;
           [ <dummy1: ACTION,ON ACTION> <action> ];
           [ FIND <cFind> ] ;
           [ <NoUpDown: NOUPDOWN> ] ;
           [ <NoMatchCase: NOMATCHCASE> ] ;
           [ <NoWholeWord: NOWHOLEWORD> ] ;
           [ CHECKDOWN <CheckDown> ] ;
           [ CHECKMATCHCASE <CheckMatchCase> ] ;
           [ CHECKWHOLEWORD <CheckWholeWord> ] ;
           [ TITLE <cTitle> ] ;
=> FindTextDlg ( <{action}>, <cFind>, <.NoUpDown.>, <.NoMatchCase.>, <.NoWholeWord.>, <CheckDown>, <CheckMatchCase>, <CheckWholeWord>, <cTitle> ) 

#xtranslate REPLACETEXTDIALOG ;
           [ <dummy1: ACTION,ON ACTION> <action> ];
           [ FIND <cFind> ] ;
           [ REPLACE <cReplace> ] ;
           [ <NoMatchCase: NOMATCHCASE> ] ;
           [ <NoWholeWord: NOWHOLEWORD> ] ;
           [ CHECKMATCHCASE <CheckMatchCase> ] ;
           [ CHECKWHOLEWORD <CheckWholeWord> ] ;
           [ TITLE <cTitle> ] ;
=> ReplaceTextDlg ( <{action}>, <cFind>, <cReplace>, <.NoMatchCase.>, <.NoWholeWord.>, <CheckMatchCase>, <CheckWholeWord> , <cTitle> )
this i use under HMG
Code (fw): Select all Collapse
     FINDTEXTDIALOG ON ACTION FindReplTXTProc() FIND cFind CHECKDOWN lDown CHECKMATCHCASE lMatchCase CHECKWHOLEWORD lWholeWord )
Code (fw): Select all Collapse
PROCEDURE FindReplTXTProc()
LOCAL lSelectFindText
LOCAL aPosRange       := { 0, 0 }
LOCAL cFind           := SP_cFindText()
LOCAL cHoleText, nPosi, hEditbox

STATIC nStart := 1

   IF FindReplaceDlg.RetValue == FRDLG_CANCEL                         // User Cancel or Close dialog
      RETURN
   ENDIF

   cFind := FindReplaceDlg.Find
   cReplace := FindReplaceDlg.Replace
   lDown := FindReplaceDlg.Down
   lMatchCase := FindReplaceDlg.MatchCase
   lWholeWord := FindReplaceDlg.WholeWord
   lSelectFindText := .T.

   SP_cFindText( cFind )
   cHoleText := TXTEdit.TXTCtrl.Value
   IF lDown = .T.
      nPosi := hb_at( UPPER( cFind ), UPPER( cHoleText ), nStart )
   ELSE
      nPosi := hb_rat( UPPER( cFind ), UPPER( cHoleText ), nStart )
   ENDIF

   IF nPosi > 0
      TXTEdit.TXTCtrl.CaretPos := nPosi
      hEditbox := GetControlHandle( "TXTCtrl", "TXTEdit" )
      SendMessage( hEditbox, EM_SETSEL, nPosi - 1, nPosi + LEN( cFind ) )
      nStart := nPosi + 1
   ELSE
      IF lDown = .T.
         MsgInfo( "EOF no more" )
         nStart := 1
      ELSE
         MsgInfo( "BOF no more" )
         nStart := LEN( cHoleText )
      ENDIF
   ENDIF

RETURN
greeting,

Jimmy
Posts: 1772
Joined: Thu Sep 05, 2019 05:32 AM
Re: how to get &quot;Userdef&quot; EVENT for ACTION
Posted: Tue Mar 28, 2023 03:55 PM
hi Antonio,
Antonio Linares wrote:Is the event sent to hwndOwner ?
i think Yes
Code (fw): Select all Collapse
  FindReplaceDlg ( NIL, lNoUpDown, lNoMatchCase, lNoWholeWord, lCheckDown, lCheckMatchCase, lCheckWholeWord, cFind, cReplace, .T., cTitle )


   HWND hWnd           = HB_ISNIL( 1 ) ? GetActiveWindow() : ( HWND ) hb_parnl( 1 );
   ...
   FindReplace.hwndOwner        = hWnd;
FindTextA function
https://learn.microsoft.com/en-us/windows/win32/api/commdlg/nf-commdlg-findtexta
The FindText function does not perform a search operation. Instead, the dialog box sends FINDMSGSTRING registered messages to the window procedure of the owner window of the dialog box. When you create the dialog box, the hwndOwner member of the FINDREPLACE structure is a handle to the owner window.
---
ReplaceTextA function
https://learn.microsoft.com/en-us/windows/win32/api/commdlg/nf-commdlg-replacetexta
The ReplaceText function does not perform a text replacement operation. Instead, the dialog box sends FINDMSGSTRING registered messages to the window procedure of the owner window of the dialog box. When you create the dialog box, the hwndOwner member of the FINDREPLACE structure is a handle to the owner window.
greeting,

Jimmy
Posts: 1772
Joined: Thu Sep 05, 2019 05:32 AM
Re: how to get &quot;Userdef&quot; EVENT for ACTION
Posted: Wed Mar 29, 2023 08:34 PM
hi,

have look into c:\fwh\source\classes\dlgfind.prg and found REDEFINE / ACTION ... hm ... :idea:

have made a copy and change into
Code (fw): Select all Collapse
   //    RegDialog( ::hWnd := FindText( cText, oWnd:hWnd, @nFindMsgString ) )
   RegDialog( ::hWnd := FindReplaceDlg( NIL, lNoUpDown, lNoMatchCase, lNoWholeWord, lCheckDown, lCheckMatchCase, lCheckWholeWord, cText, cReplace, lReplace, cTitle ) )

   REDEFINE BUTTON ID IDOK OF Self ;
           ACTION EVAL( bSearch, ;
           GetWindowText( GetWindow( GetWindow( ::hWnd, GW_CHILD ), GW_HWNDNEXT ) ), ;
           lForward, Self )

   REDEFINE BUTTON ID 0x400 OF Self ;
           ACTION MsgInfo( "400" )

   REDEFINE BUTTON ID 0x401 OF Self ;
           ACTION MsgInfo( "401" )

   REDEFINE BUTTON ID IDCANCEL OF Self ;
           ACTION nil
now i do not "wait" for Event, generate by press a Button, as i can "control" Button itself
REDEFINE is GREAT :D

p.s. i found BUTTON ID using WinID
https://dennisbabkin.com/winid/
greeting,

Jimmy
Posts: 1772
Joined: Thu Sep 05, 2019 05:32 AM
Re: how to get &quot;Userdef&quot; EVENT for ACTION
Posted: Thu Mar 30, 2023 06:33 AM
hi Antonio,
Antonio Linares wrote:If so, then you need to inherit a class from TWindow and redefine HandleEvent() method and add support for such event
Code (fw): Select all Collapse
CLASS TMyWindow FROM TWindow
   CLASSDATA lRegistered

   METHOD HandleEvent( nMsg, nWParam, nLParam )
   METHOD Notify( nIdCtrl, nPtrNMHDR ) // Common controls notifications
ENDCLASS

METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TMyWindow
   DO CASE
     CASE nMsg == _HMG_MsgIDFindDlg
         _HMG_FindReplaceOptions := FindReplaceDlgGetOptions( nLParam )
         EVAL( HMG_FindReplaceOnAction )
         IF _HMG_FindReplaceOptions[ 1 ] == 0                         // User CANCEL or CLOSE Dialog
            FindReplaceDlgRelease( .T. )                              // Destroy Dialog Window and Set NULL Dialog Handle
         ENDIF
         AFILL( _HMG_FindReplaceOptions, NIL )

     CASE nMsg == WM_POWERBROADCAST
         RETURN BROADCAST_QUERY_DENY
   ENDCASE

RETURN ::Super:HandleEvent( nMsg, nWParam, nLParam )
YES, that was the missing part

FindReplaceDlgGetOptions( nLParam ) will get "Info" of Dialog in a Array AFTER i press a Button in Dialog
Code (fw): Select all Collapse
         _HMG_FindReplaceOnAction := { || FindReplTXTProc(oMGet,cFind,cMemo) }
         DlgFindReplace( @cFind, oWnd, { || nil }, ;
                                        lReplace, cReplace, cTitle, lNoUpDown, lNoMatchCase, lNoWholeWord, lCheckDown, lCheckMatchCase, lCheckWholeWord )
i need to call as "other" Codeblock "_HMG_FindReplaceOnAction" which run under "TMyWindow"
greeting,

Jimmy

Continue the discussion