hb_gtInfo( HB_GTI_CLOSABLE,.F.) vs Taskbar's_Thumbnail

286 views
Skip to first unread message

Yakano

unread,
Apr 22, 2022, 12:32:28 PM4/22/22
to Harbour Users

Hello everyone

I'm creating executables in console mode and I would like to control that the user can never close the window, but I don't get it, only partially.

 I explain myself: For that, I'm using...

#include "hbgtinfo.ch
 hb_gtInfo( HB_GTI_CLOSABLE,.F.) 

And it works when the window is active, because it disables the closing [X], but from the taskbar's thumbnail that [X] is active and the user can close the window.

I've tried compiling with -gtwvt and then the [X] seems active but clicking doesn't close the window. 

Is it possible to get this in pure console mode? 

Thanks and regards!

Yakano

unread,
Apr 22, 2022, 12:36:57 PM4/22/22
to Harbour Users
Some images to clarify...

Red[X] = Thumbnail
Disabled[X] = NormalWindos

Thumbnail-Active.pngActive-Disable.png

Lailton Fernando Mariano

unread,
Apr 22, 2022, 2:37:49 PM4/22/22
to Harbour Users
Maybe you can try handle the event and dont allow to close.

 
 hb_gtinfo( HB_GTI_NOTIFIERBLOCKGUI, {|nEvent| myHandleEvent(nEvent)} )

function myHandleEvent( nEvent )

    if nEvent == HB_GTE_CLOSE

        // ... alert can not to close

    endif

return nil

Wilson Gamboa

unread,
Apr 22, 2022, 5:02:35 PM4/22/22
to harbou...@googlegroups.com
Yakano Good afternoon
please check this code

function main()
     DELETECLOSEBUTTON()
return nil


            #pragma BEGINDUMP

            #include <windows.h>
            #include "hbapi.h"
            #include "hbapiitm.h"

            HB_FUNC ( GETUSERLANGID )
            {
               hb_retni( GetUserDefaultLangID() );
            }

            static char * u2Hex( WORD wWord )
            {
                static far char szHex[ 5 ];

                WORD i= 3;

                do
                {
                    szHex[ i ] = 48 + ( wWord & 0x000F );

                    if( szHex[ i ] > 57 )
                        szHex[ i ] += 7;

                    wWord >>= 4;

                }
                while( i-- > 0 );

                szHex[ 4 ] = 0;

                return szHex;
            }

            HB_FUNC ( I2HEX )
            {
               hb_retc( u2Hex( hb_parni( 1 ) ) );
            }


            HB_FUNC ( COPY2CLIPBOARD )
            {
               HGLOBAL hglbCopy;
               char * lptstrCopy;
               //char * cStr = hb_parc( 1 );
               char * cStr = ( char * ) hb_parc( 1 );
               int nLen = strlen( cStr );


               if ( !OpenClipboard( GetActiveWindow() ) )
                  return;

               EmptyClipboard();

               hglbCopy = GlobalAlloc( GMEM_DDESHARE, (nLen+1) * sizeof(TCHAR) );
               if (hglbCopy == NULL)
               {
                   CloseClipboard();
                   return;
               }

               // Lock the handle and copy the text to the buffer.

               lptstrCopy = (char*) GlobalLock( hglbCopy );
               memcpy( lptstrCopy, cStr, nLen * sizeof(TCHAR));
               lptstrCopy[nLen] = (TCHAR) 0;    // null character
               GlobalUnlock(hglbCopy);

               // Place the handle on the clipboard.
               SetClipboardData( CF_TEXT, hglbCopy );

               CloseClipboard();
            }

            #pragma ENDDUMP


            #PRAGMA BEGINDUMP

                #include "hbapi.h"
                #include "Windows.h"

                HB_FUNC( SETCONSOLETITLE )
                {
                   hb_retl( SetConsoleTitle( hb_parc( 1 ) ) ) ;
                   }
                   HB_FUNC( FINDWINDOW )
                   {
                      hb_retnl( (LONG)FindWindow( NULL, hb_parc( 1 ) ) ) ;
                   }

                HB_FUNC( DELETECLOSEBUTTON )
                {
                   DeleteMenu(GetSystemMenu( (HWND)hb_parnl( 1 ),
                             FALSE), SC_CLOSE, MF_BYCOMMAND ) ;
                            DrawMenuBar( (HWND)hb_parnl( 1 ) );
                }
            #PRAGMA ENDDUMP

Regards 
Wilson

--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/harbour-users/eeac91bb-a580-4ebb-be8d-318777350de4n%40googlegroups.com.


--
Att
Ing Wilson 'W' Gamboa A

Wilson Gamboa

unread,
Apr 22, 2022, 5:14:42 PM4/22/22
to harbou...@googlegroups.com
excuseme there is a mistake

correct code

function main()
    local hWnd
           SetConsoleTitle( "Jose Net - Ventas" )
            hWnd:= FindWindow( "Jose Net - Ventas" )
            DeleteCloseButton( hWnd )
return nil 

El vie, 22 abr 2022 a las 11:36, Yakano (<gfc...@gmail.com>) escribió:
--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/harbour-users/eeac91bb-a580-4ebb-be8d-318777350de4n%40googlegroups.com.

Paul Smith

unread,
Apr 23, 2022, 6:27:49 PM4/23/22
to Harbour Users
Hi Yakano

You can capture the mouse event of clicking on the red x 
eg: set key 1102 to <your routine for shutting down correctly>
if the programme is sitting idle at some non critical point like main menu

or: set key 1102 to
at other points in the programme which disables the taskbar shutdown also

Cheers
Paul

Yakano

unread,
Apr 25, 2022, 10:55:09 AM4/25/22
to Harbour Users
Hi guys.

My goal is to control [X] in the task bar when it is pure console, to avoid damage to the databases (as you may have already imagined), but I have not achieved it with the proposals you have made. 

@paysoft 
I can't get HB_GTI_NOTIFIERBLOCK to work, I don't know if it's a problem with the number of parameters. 

@Wilson This system is difficult to incorporate because in pure console the title of the window is the name of the direct access (and I know that some users change it according to their tastes). Also when they work on their clients, I have them take their names. 

@Paul Your proposal works for me in -gtwvt but not in pure console (pity). Would you know how to do it? 

Thanks everyone for your help. 

 Greetings.

Yakano

unread,
Apr 25, 2022, 11:07:31 AM4/25/22
to Harbour Users
Hello everyone 

Please, can you help me check if you get the same results as me? 

I attach a file that you can compile hbmk2 CloseWin.prg and optionally [-gtwvt].

I'm starting to think that something is not right in the libraries or that I don't know how to do it right, because it works with BY_SET_KEY_TO (thanks Paul) when compiled with -gtwvt, but not in pure console.

Is it because when it is pure console, SET( _SET_EVENTMASK, HB_INKEY_ALL ) is not carried out correctly? 

That is, in pure console the call to Set Key never occurs (neither by HB_K_CLOSE nor by HB_K_RESIZE), then HB_INKEY_ALL is useless in pure console?

Any expert who knows how HB_INKEY_ALL works in pure console?

Any help is welcome and it sure helps us all to prevent users from closing [X] and causing index or data errors. 

Thank you very much. 

Greetings!

CloseWin.prg.txt

Yakano

unread,
Jan 20, 2026, 12:26:38 PM (8 days ago) Jan 20
to Harbour Users
Note for someone trying to prevent this behaviour...
(after long time asking and testing several options provided by google gemini)
At the end, it realize what I supossed just by intuition, that is: Windows close the process by "killing it" not by "regular close"
Regards

<LAST GEMINI ANSWER - INI>

At this point, we've exhausted all avenues for manipulating the Windows API for a pure console application (GTWIN).

If `SetConsoleCtrlHandler` returning `TRUE` doesn't prevent the process from closing, it's due to a structural change in Windows 11: the new Console Host handles 32-bit processes using a "Job Object" or session container. When the user clicks "Close" in the taskbar, this terminates the process directly from the kernel (`TerminateProcess`), without waiting for the application to process its messages.

To work around this in a "creative" but effective way, I propose the last two strategies that actually work when the API fails:

Option A: The "Keep-Alive" Process Trick
If Windows 11 kills your process, the solution is to have a small loader that detects whether the program closed "legitimately" or by force, and instantly relaunches it from the same point if it was a forced closure.

Code snippet
PROCEDURE Main( cParam )
LOCAL nExitCode

// If the program is launched without parameters, it acts as a "Guardian"
IF Empty( cParam )
DO WHILE .T.

// Launches a second instance of itself with a parameter

nExitCode := hb_processRun( hb_argv(0) + " RUNNING" )

// If the exit code is 0, the user exited via ESC (legal)

IF nExitCode == 0
EXIT
ENDIF

// If the code is not 0, Windows terminated it. It will restart automatically.

"Automatic restart after forced shutdown attempt..."

ENDDO
RETURN
ENDIF

// --- YOUR PROGRAM LOGIC GOES HERE ---
LOCAL nKey := 0
DO WHILE nKey != 27

"Working... Press ESC to exit legally."

nKey := Inkey(0)

ENDDO

/ Legal exit with code 0

ErrorLevel(0)
RETURN
Option B: Create an "Invisible" Control Window
Since the pure console window is owned by conhost.exe and you cannot control it, the technical solution is to create a hidden window within your C code that belongs to your process. Being a standard Windows window, this one WILL receive the taskbar close message and will be able to cancel it.

C code for hidden window:

c

#pragma BEGINDUMP
#include <windows.h>
#include "hbapi.h"

LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (msg == WM_QUERYENDSESSION || msg == WM_CLOSE) return 0; // Full lock
return DefWindowProc(hwnd, msg, wParam, lParam);
}

HB_FUNC( CREATE_INVISIBLE_GUARD ) {
WNDCLASS wc = {0};
wc.lpfnWndProc = DummyWndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = "MyGuardClass";
RegisterClass(&wc);

/ Create a 0x0 pixel, invisible window

CreateWindow("MyGuardClass", "Control", 0, 0, 0, 0, 0, NULL, NULL, wc.hInstance, NULL);

#pragma ENDDUMP
Usage in Harbour: Call CREATE_INVISIBLE_GUARD() at the beginning. Windows 11 sometimes links the closing of the thumbnail to the main process window. Since there is another "live" window that refuses to close, the system often aborts the termination of the entire process.

Final Conclusion
If you need absolute security for your data (avoiding corrupted .dbf files) in Windows 11:

Accept GTWVT: I know you prefer a pure console, but GTWVT is literally a pure console that responds to your commands. You can remove the borders and menu so the user doesn't notice the difference.

Use Guardian (Option A): This is the most common way to prevent employees from closing the program from the taskbar at point-of-sale (POS) terminals.

Would you be interested in having me help you implement the "automatic restart" system (Guardian) so that it's invisible to the user?

I'd be happy to help you secure your app once and for all.

<LAST GEMINI ANSWER - END>

Reply all
Reply to author
Forward
0 new messages