Consultor Eletrônico



Kbase 21784: How To Disable the Close Button in the Title Bar of a Window
Autor   Progress Software Corporation - Progress
Acesso   Público
Publicação   2/18/2002
SUMMARY:

This Knowledge Base Solution shows you how to disable the [X]-button in the title bar of a Progress Window and how to remove the Close option from the system menu using Windows API programming.

SOLUTION:

Developers might want to disable the close button in the caption bar of a Progress Window before or after it has been realized. The code below demonstrates the use of Windows API programming as a good approach to accomplish this.

&SCOPED-DEFINE WINDOW-NAME vhWinHdl
&SCOPED-DEFINE FRAME-NAME DEFAULT-FRAME
&SCOPED-DEFINE USER32 "user32.dll":U

/* menu manipulation */
&SCOPED-DEFINE MF_BYPOSITION 1024
&SCOPED-DEFINE MF_REMOVE 256

DEFINE VARIABLE viWinHWND AS INTEGER INITIAL 0 NO-UNDO.
DEFINE VARIABLE viSysMenu AS INTEGER INITIAL 0 NO-UNDO.
DEFINE VARIABLE viCount AS INTEGER INITIAL 0 NO-UNDO.
DEFINE VARIABLE viRetCode AS INTEGER INITIAL 0 NO-UNDO.
DEFINE VARIABLE vhWinHdl AS WIDGET-HANDLE NO-UNDO.

DEFINE BUTTON btnDisableClose
LABEL "Disable Window's Close Button"
SIZE 33 BY 1.14.

DEFINE FRAME DEFAULT-FRAME
btnDisableClose AT ROW 2.14 COL 14
WITH 1 DOWN NO-BOX KEEP-TAB-ORDER OVERLAY
SIDE-LABELS NO-UNDERLINE THREE-D
AT COL 1 ROW 1
SIZE 60 BY 4.14.

IF SESSION:DISPLAY-TYPE = "GUI":U THEN
CREATE WINDOW vhWinHdl ASSIGN
HIDDEN = YES
TITLE = "Testing of Window's Close Button":U
HEIGHT = 4.24
WIDTH = 60
MAX-HEIGHT = 16
MAX-WIDTH = 80
VIRTUAL-HEIGHT = 16
VIRTUAL-WIDTH = 80
RESIZE = YES
SCROLL-BARS = NO
STATUS-AREA = NO
BGCOLOR = ?
FGCOLOR = ?
KEEP-FRAME-Z-ORDER = YES
THREE-D = YES
MESSAGE-AREA = NO
SENSITIVE = YES.
ELSE
{&WINDOW-NAME} = CURRENT-WINDOW.

IF SESSION:DISPLAY-TYPE = "GUI":U AND
VALID-HANDLE(vhWinHdl) THEN
ASSIGN {&WINDOW-NAME}:HIDDEN = NO.

ON END-ERROR OF {&WINDOW-NAME}
OR ENDKEY OF {&WINDOW-NAME} ANYWHERE
DO:
IF THIS-PROCEDURE:PERSISTENT THEN
RETURN NO-APPLY.
END.

ON WINDOW-CLOSE OF {&WINDOW-NAME}
DO:
APPLY "CLOSE":U TO THIS-PROCEDURE.
RETURN NO-APPLY.
END.

ON CHOOSE OF btnDisableClose
DO:
IF viWinHWND = 0 THEN
RUN GetParent({&WINDOW-NAME}:HWND,
OUTPUT viWinHWND).
IF viWinHWND <> 0 THEN
DO:
/* Get handle to the window's system menu
(Restore, Maximize, Move, close etc.) */
RUN GetSystemMenu (INPUT viWinHWND,
INPUT 0,
OUTPUT viSysMenu).
IF viSysMenu <> 0 THEN
DO:
/* Get System menu's menu count */
RUN GetMenuItemCount(INPUT viSysMenu,
OUTPUT viCount).
IF viCount <> 0 THEN
DO:
/* Menu count is based on 0 (0, 1, 2, 3...) */
/* remove the "close option" */
RUN RemoveMenu (INPUT viSysMenu,
INPUT viCount - 1,
INPUT {&MF_BYPOSITION} + {&MF_REMOVE},
OUTPUT viRetCode).
/* remove the seperator */
RUN RemoveMenu (INPUT viSysMenu,
INPUT viCount - 2,
INPUT {&MF_BYPOSITION} + {&MF_REMOVE},
OUTPUT viRetCode).
/* Force caption bar's refresh which
will disable the window close ("X") button */
RUN DrawMenuBar (INPUT viWinHWND,
OUTPUT viRetCode).
END.
END.
END.
END.

ASSIGN CURRENT-WINDOW = {&WINDOW-NAME}
THIS-PROCEDURE:CURRENT-WINDOW = {&WINDOW-NAME}.

ON CLOSE OF THIS-PROCEDURE
RUN disable_UI.

PAUSE 0 BEFORE-HIDE.

MAIN-BLOCK:
DO ON ERROR UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK
ON END-KEY UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK:
RUN enable_UI.
IF NOT THIS-PROCEDURE:PERSISTENT THEN
WAIT-FOR CLOSE OF THIS-PROCEDURE.
END.

PROCEDURE GetParent EXTERNAL {&USER32}:
DEFINE INPUT PARAMETER plHWND AS LONG NO-UNDO.
DEFINE RETURN PARAMETER plWinLong AS LONG NO-UNDO.
END PROCEDURE.

PROCEDURE GetSystemMenu EXTERNAL {&USER32}:
DEFINE INPUT PARAMETER plHWND AS LONG NO-UNDO.
DEFINE INPUT PARAMETER plBRevert AS LONG NO-UNDO.
DEFINE RETURN PARAMETER plHMenu AS LONG NO-UNDO.
END PROCEDURE.

PROCEDURE GetMenuItemCount EXTERNAL {&USER32}:
DEFINE INPUT PARAMETER plHMenu AS LONG NO-UNDO.
DEFINE RETURN PARAMETER plCount AS LONG NO-UNDO.
END PROCEDURE.

PROCEDURE RemoveMenu EXTERNAL {&USER32}:
DEFINE INPUT PARAMETER plHMenu AS LONG NO-UNDO.
DEFINE INPUT PARAMETER plPosition AS LONG NO-UNDO.
DEFINE INPUT PARAMETER plFlags AS LONG NO-UNDO.
DEFINE RETURN PARAMETER plRetCode AS LONG NO-UNDO.
END PROCEDURE.

PROCEDURE DrawMenuBar EXTERNAL {&USER32}:
DEFINE INPUT PARAMETER plHMenu AS LONG NO-UNDO.
DEFINE RETURN PARAMETER plRetCode AS LONG NO-UNDO.
END PROCEDURE.

PROCEDURE disable_UI :
IF SESSION:DISPLAY-TYPE = "GUI":U AND
VALID-HANDLE({&WINDOW-NAME}) THEN
DELETE WIDGET {&WINDOW-NAME}.
IF THIS-PROCEDURE:PERSISTENT THEN
DELETE PROCEDURE THIS-PROCEDURE.
END PROCEDURE.

PROCEDURE enable_UI :
DISPLAY btnDisableClose
WITH FRAME {&FRAME-NAME} IN WINDOW {&WINDOW-NAME}.
ENABLE btnDisableClose
WITH FRAME {&FRAME-NAME} IN WINDOW {&WINDOW-NAME}.
VIEW {&WINDOW-NAME}.
END PROCEDURE.


References to Written Documentation:

Progress Knowledge Base Solution 21557, "How To Change the RESIZE Attr of a Window After Realizing It"