en un post anterior se pidió como evitar el movimiento de una ventana.
Para ello varios de nosotros propusimos algunas formas,jparada wrote:Is there any way (or trick) to prevent a user can not move a window by clicking on the title bar of the window (I hope I've explained).
viewtopic.php?p=9294&sid=4a2a85bc2346e7 ... 18ca#p9294
pero los resultados finales no resultaron del todo satisfactorio, por ejemplo, no se pudo evitar
que el usuario arrastrara la ventana con el mouse, auque al soltarla esta vovia al lugar, lo mismo sucedia con el boton de maximizar.
A pesar que la mayoria no le gusto la idea de tener una ventana fija en el monitor, no deja de ser un buen ejercicio de programacion
intentar hacerlo.
Yo intente ir un poco mas lejos, y desarrolle algunas funciones que permiten bloquear las acciones del menu del sistema de una ventana determinada, con lo cual
elimina los inconvenientes que tenian las soluciones anteriormente propuestas.
*****************************************************************************************************************
* DESCRIPCION:
*
* Bloquea o Desbloquea los comandos del menu del sistema (MOVE, SIZE, RESTORE, MAXIMIZE, MINIMIZE, CLOSE)
*
* de una determinada ventana al interceptar los mensajes WM_SYSCOMMAND que el sistema le envia a dicha ventana
*
* Con estas funciones se pueden evitar que el usuario mueva, cambie de tamaño, maximize, minimize, restablezca
*
* y/o cierre una ventana con el menu del sistema o con los botones del sistema en tiempo de ejecución.
*
*****************************************************************************************************************
*****************************************************************************************************************
* SINTAXIS:
*
* Definiciones de ID_n:
*
* #define ID_MOVE 1
* #define ID_SIZE 2
* #define ID_RESTORE 3
* #define ID_MAXIMIZE 4
* #define ID_MINIMIZE 5
* #define ID_CLOSE 6
* #define ID_ALL 7
*
* IS_SYSMENU_LOCK (WinName, ID_n)
* //Retorna .T. si ID_n de la ventana WinName esta bloqueado (LOCK)
* //Retorna .F. si ID_n de la ventana WinName esta desbloqueado (UNLOCK)
*
* LOCK SYSMENU IN WINDOW <WinName> ALL //Bloquea todos los ID_n de la ventana WinName
* UNLOCK SYSMENU IN WINDOW <WinName> ALL //Desbloquea todos los ID_n de la ventana WinName
*
* LOCK SYSMENU IN WINDOW <WinName> [MOVE] [SIZE] [RESTORE] [MAXIMIZE] [MINIMIZE] [CLOSE]
* // Bloquea solo los parametros especificados y
* // automaticamente desbloquea los no especificados
*******************************************************************************************************
La solucion definitiva al pedido de Jparada seria:
Code: Select all
LOCK SYSMENU IN WINDOW "Form_1" MAXIMIZE MOVE SIZE
toda ventana tiene asociado un procedimiento (funcion definida por el usuario, genericamente denominada WndProc) que recibe y procesa los mensajes que el sistema
le envia a dicha ventana, yo lo que ago es sustituir el WndProc original por uno nuevo que filtra los mensajes que recibe la ventana, si son mensajes generado
por el accionar del menu del sistema de la ventana (WM_SYSCOMMAND) yo los proceso si corresponde, de lo contrario le paso los mensajes al WndProc original para
que el los procese. En definitiva lo encadeno al WndProc nuevo el WndProc original.
Con estas funciones se pueden evitar que el usuario mueva, cambie de tamaño, maximize, minimize, restablezca y/o cierre una ventana con el menu del sistema o
con los botones del sistema en tiempo de ejecucion.
Obviamente que la mayoria de estas acciones ya estan implementadas al definir una ventana, pero estan disponibles solo en tiempo de definición.
Aqui les dejo el codigo fuente, espero que les sirva para algo.
Saludos a todos,
Claudio Soto
Code: Select all
*****************************************************************************************************************
* PROGRAMA: LOCK SYSMENU IN WINDOW
* LENGUAJE: HARBOUR-MINIGUI 3.0.27
* FECHA: 9 ABRIL 2010
* AUTOR: Dr. CLAUDIO SOTO
* PAIS: URUGUAY
* E-MAIL: srvet@adinet.com.uy
*****************************************************************************************************************
*****************************************************************************************************************
* DESCRIPCION:
*
* Bloquea o Desbloquea los comandos del menu del sistema (MOVE, SIZE, RESTORE, MAXIMIZE, MINIMIZE, CLOSE)
* de una determinada ventana al interceptar los mensajes WM_SYSCOMMAND que el sistema le envia a dicha ventana
*
* Con estas funciones se pueden evitar que el usuario mueva, cambie de tamaño, maximize, minimize, restablezca
* y/o cierre una ventana con el menu del sistema o con los botones del sistema en tiempo de ejecucion.
*****************************************************************************************************************
*****************************************************************************************************************
* SINTAXIS:
*
* Definiciones de ID_n:
*
* #define ID_MOVE 1
* #define ID_SIZE 2
* #define ID_RESTORE 3
* #define ID_MAXIMIZE 4
* #define ID_MINIMIZE 5
* #define ID_CLOSE 6
* #define ID_ALL 7
*
* IS_SYSMENU_LOCK (WinName, ID_n) //Retorna .T. si ID_n de la ventana WinName esta bloqueado (LOCK)
* //Retorna .F. si ID_n de la ventana WinName esta desbloqueado (UNLOCK)
*
* LOCK SYSMENU IN WINDOW <WinName> ALL //Bloquea todos los ID_n de la ventana WinName
* UNLOCK SYSMENU IN WINDOW <WinName> ALL //Desbloquea todos los ID_n de la ventana WinName
*
* LOCK SYSMENU IN WINDOW <WinName> [MOVE] [SIZE] [RESTORE] [MAXIMIZE] [MINIMIZE] [CLOSE]
* // Bloquea solo los parametros especificados y
* // automaticamente desbloquea los no especificados
*******************************************************************************************************
*******************************************************************************************************
* DEFINICION DE LOS COMANDOS
*******************************************************************************************************
#define ID_MOVE 1
#define ID_SIZE 2
#define ID_RESTORE 3
#define ID_MAXIMIZE 4
#define ID_MINIMIZE 5
#define ID_CLOSE 6
#define ID_ALL 7
#command LOCK SYSMENU IN WINDOW <WinName> ALL;
=> LOCK_SYSMENU_WIN (<WinName>,.T.,.T.,.T.,.T.,.T.,.T.)
#command UNLOCK SYSMENU IN WINDOW <WinName> ALL;
=> LOCK_SYSMENU_WIN (<WinName>,.F.,.F.,.F.,.F.,.F.,.F.)
#command LOCK SYSMENU IN WINDOW <WinName> [<mov: MOVE>] [<siz: SIZE>] [<res: RESTORE>] [<max: MAXIMIZE>] [<min: MINIMIZE>] [<clo: CLOSE>];
=> LOCK_SYSMENU_WIN (<WinName>, <.mov.>, <.siz.>, <.res.>, <.max.>, <.min.>, <.clo.>)
// IS_SYSMENU_LOCK (WinName, ID_n)
******************************************************************************************************
#include "minigui.ch"
Function Main
DEFINE WINDOW Form_1 ;
AT 0,0 ;
WIDTH 400 ;
HEIGHT 500 ;
TITLE 'LOCK SYSMENU IN WINDOW' ;
MAIN
DEFINE MAIN MENU
DEFINE POPUP '&Lock'
ITEM "Lock: MOVE + SIZE" ACTION accion (3)
ITEM "Lock: MINIMIZE + MAXIMIZE" ACTION accion (4)
ITEM "Lock: MOVE + SIZE + MAXIMIZE" ACTION accion (5)
ITEM "Lock: MOVE + SIZE + MAXIMIZE + MINIMIZE" ACTION accion (6)
END POPUP
END MENU
@ 50, 100 BUTTON boton_1 CAPTION "LOCK ALL" ACTION accion (1)
@ 50, 250 BUTTON boton_2 CAPTION "UNLOCK ALL" ACTION accion (2)
@ 150, 100 LABEL label_1 AUTOSIZE BOLD
@ 175, 100 LABEL label_2 AUTOSIZE BOLD
@ 200, 100 LABEL label_3 AUTOSIZE BOLD
@ 225, 100 LABEL label_4 AUTOSIZE BOLD
@ 250, 100 LABEL label_5 AUTOSIZE BOLD
@ 275, 100 LABEL label_6 AUTOSIZE BOLD
@ 100, 100 LABEL label_7 AUTOSIZE BOLD
@ 350, 100 BUTTON boton_3 CAPTION "Lock All win2" ACTION vent2 (1)
@ 350, 250 BUTTON boton_4 CAPTION "Unlock All win2" ACTION vent2 (2)
accion (0)
END WINDOW
Form_1.Center
Form_1.Activate
Return
Procedure accion (n)
DO CASE
CASE n = 1
LOCK SYSMENU IN WINDOW "Form_1" ALL
CASE n = 2
UNLOCK SYSMENU IN WINDOW "Form_1" ALL
CASE n = 3
LOCK SYSMENU IN WINDOW "Form_1" MOVE SIZE
CASE n = 4
LOCK SYSMENU IN WINDOW "Form_1" MINIMIZE MAXIMIZE
CASE n = 5
LOCK SYSMENU IN WINDOW "Form_1" MAXIMIZE MOVE SIZE
CASE n = 6
LOCK SYSMENU IN WINDOW "Form_1" MAXIMIZE MOVE SIZE MINIMIZE
END CASE
Form_1.Label_1.Value := "Lock MOVE: " +IF (IS_SYSMENU_LOCK ("Form_1", ID_MOVE),"True","False")
Form_1.Label_2.Value := "Lock SIZE: " +IF (IS_SYSMENU_LOCK ("Form_1", ID_SIZE),"True","False")
Form_1.Label_3.Value := "Lock RESTORE: " +IF (IS_SYSMENU_LOCK ("Form_1", ID_RESTORE),"True","False")
Form_1.Label_4.Value := "Lock MAXIMIZE: " +IF (IS_SYSMENU_LOCK ("Form_1", ID_MAXIMIZE),"True","False")
Form_1.Label_5.Value := "Lock MINIMIZE: " +IF (IS_SYSMENU_LOCK ("Form_1", ID_MINIMIZE),"True","False")
Form_1.Label_6.Value := "Lock CLOSE: " +IF (IS_SYSMENU_LOCK ("Form_1", ID_CLOSE),"True","False")
Form_1.Label_7.Value := "Lock ALL: " +IF (IS_SYSMENU_LOCK ("Form_1", ID_ALL),"True","False")
Form_1.Label_1.FontColor := IF (IS_SYSMENU_LOCK ("Form_1", ID_MOVE),RED,BLUE)
Form_1.Label_2.FontColor := IF (IS_SYSMENU_LOCK ("Form_1", ID_SIZE),RED,BLUE)
Form_1.Label_3.FontColor := IF (IS_SYSMENU_LOCK ("Form_1", ID_RESTORE),RED,BLUE)
Form_1.Label_4.FontColor := IF (IS_SYSMENU_LOCK ("Form_1", ID_MAXIMIZE),RED,BLUE)
Form_1.Label_5.FontColor := IF (IS_SYSMENU_LOCK ("Form_1", ID_MINIMIZE),RED,BLUE)
Form_1.Label_6.FontColor := IF (IS_SYSMENU_LOCK ("Form_1", ID_CLOSE),RED,BLUE)
Form_1.Label_7.FontColor := IF (IS_SYSMENU_LOCK ("Form_1", ID_ALL),RED,BLUE)
Return
Procedure vent2 (n)
IF IsWindowDefined (Form_2) = .F.
DEFINE WINDOW Form_2 ;
AT 100,100 ;
WIDTH 200 ;
HEIGHT 300 ;
TITLE 'Win 2';
CHILD
@ 10, 10 LABEL label_8 AUTOSIZE BOLD
END WINDOW
END
IF n = 1
LOCK SYSMENU IN WINDOW "Form_2" ALL
ELSE
UNLOCK SYSMENU IN WINDOW "Form_2" ALL
ENDIF
Form_2.Label_8.Value := "Lock ALL Win 2: " +IF (IS_SYSMENU_LOCK ("Form_2", ID_ALL),"True","False")
Form_2.Label_8.FontColor := IF (IS_SYSMENU_LOCK ("Form_2", ID_ALL),RED,BLUE)
IF IsWindowActive (Form_2) = .F.
Form_2.activate
ENDIF
Return
*#########################################################################################################################
* IMPLEMENTACION DE LAS FUNCIONES
*#########################################################################################################################
#define ID_MOVE 1
#define ID_SIZE 2
#define ID_RESTORE 3
#define ID_MAXIMIZE 4
#define ID_MINIMIZE 5
#define ID_CLOSE 6
#define ID_ALL 7
Function IS_SYSMENU_LOCK (WinName, ID_n)
DO CASE
CASE ID_n = ID_MOVE
Return IS_CHECK_ARRAY (GetFormHandle (WinName), ID_MOVE)
CASE ID_n = ID_SIZE
Return IS_CHECK_ARRAY (GetFormHandle (WinName), ID_SIZE)
CASE ID_n = ID_RESTORE
Return IS_CHECK_ARRAY (GetFormHandle (WinName), ID_RESTORE)
CASE ID_n = ID_MAXIMIZE
Return IS_CHECK_ARRAY (GetFormHandle (WinName), ID_MAXIMIZE)
CASE ID_n = ID_MINIMIZE
Return IS_CHECK_ARRAY (GetFormHandle (WinName), ID_MINIMIZE)
CASE ID_n = ID_CLOSE
Return IS_CHECK_ARRAY (GetFormHandle (WinName), ID_CLOSE)
CASE ID_n = ID_ALL
IF IS_CHECK_ARRAY (GetFormHandle (WinName), ID_MOVE) .AND.;
IS_CHECK_ARRAY (GetFormHandle (WinName), ID_SIZE) .AND.;
IS_CHECK_ARRAY (GetFormHandle (WinName), ID_RESTORE) .AND.;
IS_CHECK_ARRAY (GetFormHandle (WinName), ID_MAXIMIZE) .AND.;
IS_CHECK_ARRAY (GetFormHandle (WinName), ID_MINIMIZE) .AND.;
IS_CHECK_ARRAY (GetFormHandle (WinName), ID_CLOSE)
Return .T.
ELSE
Return .F.
ENDIF
END CASE
Return .F.
Procedure LOCK_SYSMENU_WIN (WinName, MOVE, SIZE, RESTORE, MAXIMIZE, MINIMIZE, CLOSE, ALL)
IF ALL = .T.
SET_ARRAY_DATOS (GetFormHandle (WinName),.T.,.T.,.T.,.T.,.T.,.T.)
ELSE
SET_ARRAY_DATOS (GetFormHandle (WinName), MOVE, SIZE, RESTORE, MAXIMIZE, MINIMIZE, CLOSE)
ENDIF
Return
Procedure UNLOCK_SYSMENU_WIN (WinName)
SET_ARRAY_DATOS (GetFormHandle (WinName),.F.,.F.,.F.,.F.,.F.,.F.)
Return
*#########################################################################################################################
* FUNCIONES EN C
*#########################################################################################################################
#pragma begindump
#include <windows.h>
#include "hbapi.h"
#include "hbapiitm.h"
LONG GetArray_Old_WndProc (HWND hWnd);
LRESULT CALLBACK WndProc_PIRATA (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
WNDPROC p_WndProc_old;
BOOL flag = FALSE;
INT cont = 0;
PHB_ITEM pArray_HWND;
PHB_ITEM pArray_MOVE;
PHB_ITEM pArray_SIZE;
PHB_ITEM pArray_RESTORE;
PHB_ITEM pArray_MAXIMIZE;
PHB_ITEM pArray_MINIMIZE;
PHB_ITEM pArray_CLOSE;
PHB_ITEM pArray_Old_WndProc;
HB_FUNC (SET_ARRAY_DATOS)
{ int i;
HWND hWND;
// Si no existe crea la matriz que contiene los datos de las ventanas
if (flag == FALSE)
{ flag = TRUE;
cont = 0;
pArray_HWND = hb_itemNew (NULL);
pArray_MOVE = hb_itemNew (NULL);
pArray_SIZE = hb_itemNew (NULL);
pArray_RESTORE = hb_itemNew (NULL);
pArray_MAXIMIZE = hb_itemNew (NULL);
pArray_MINIMIZE = hb_itemNew (NULL);
pArray_CLOSE = hb_itemNew (NULL);
pArray_Old_WndProc = hb_itemNew (NULL);
hb_arrayNew (pArray_HWND, 0);
hb_arrayNew (pArray_MOVE, 0);
hb_arrayNew (pArray_SIZE, 0);
hb_arrayNew (pArray_RESTORE, 0);
hb_arrayNew (pArray_MAXIMIZE, 0);
hb_arrayNew (pArray_MINIMIZE, 0);
hb_arrayNew (pArray_CLOSE, 0);
hb_arrayNew (pArray_Old_WndProc, 0);
}
// Verifica si la ventana ya esta registrada y cambia el valor de los datos
for (i=1; i <= cont; i++)
{ if (hb_arrayGetNL (pArray_HWND, i) == hb_parnl (1))
{
//hb_arraySetNL(pArray_HWND, i, hb_parnl (1));
hb_arraySetL (pArray_MOVE, i, hb_parl (2));
hb_arraySetL (pArray_SIZE, i, hb_parl (3));
hb_arraySetL (pArray_RESTORE, i, hb_parl (4));
hb_arraySetL (pArray_MAXIMIZE, i, hb_parl (5));
hb_arraySetL (pArray_MINIMIZE, i, hb_parl (6));
hb_arraySetL (pArray_CLOSE, i, hb_parl (7));
return;
}
}
// Al no estar la ventana registrada, adiciona un elemento a la matriz y le agrega los datos
cont++;
hb_arraySize (pArray_HWND, cont);
hb_arraySize (pArray_MOVE, cont);
hb_arraySize (pArray_SIZE, cont);
hb_arraySize (pArray_RESTORE, cont);
hb_arraySize (pArray_MAXIMIZE, cont);
hb_arraySize (pArray_MINIMIZE, cont);
hb_arraySize (pArray_CLOSE, cont);
hb_arraySize (pArray_Old_WndProc, cont);
hb_arraySetNL(pArray_HWND, cont, hb_parnl (1));
hb_arraySetL (pArray_MOVE, cont, hb_parl (2));
hb_arraySetL (pArray_SIZE, cont, hb_parl (3));
hb_arraySetL (pArray_RESTORE, cont, hb_parl (4));
hb_arraySetL (pArray_MAXIMIZE, cont, hb_parl (5));
hb_arraySetL (pArray_MINIMIZE, cont, hb_parl (6));
hb_arraySetL (pArray_CLOSE, cont, hb_parl (7));
// Cambia el procedimiento de ventana original por WndProc_PIRATA, quien a su vez luego
// de procesar WM_SYSCOMMAND engancha (llama) al procedimiento original
hWND = (HWND) hb_parnl (1);
p_WndProc_old = (WNDPROC) SetWindowLongPtr(hWND, GWLP_WNDPROC, (LONG_PTR) WndProc_PIRATA);
hb_arraySetNL (pArray_Old_WndProc, cont, (LONG) p_WndProc_old);
// InvalidateRect(hWND, NULL, TRUE);
// UpdateWindow(hWND);
}
#define ID_MOVE 1
#define ID_SIZE 2
#define ID_RESTORE 3
#define ID_MAXIMIZE 4
#define ID_MINIMIZE 5
#define ID_CLOSE 6
BOOL CheckArray (HWND hWND, int ID)
{ int i;
// Verifica si la ventana ya esta registrada y devuelve el valor de los datos
for (i=1; i <= cont; i++)
{ if ((HWND) hb_arrayGetNL (pArray_HWND, i) == hWND)
{
switch (ID)
{
case ID_MOVE:
return hb_arrayGetL(pArray_MOVE, i);
case ID_SIZE:
return hb_arrayGetL(pArray_SIZE, i);
case ID_RESTORE:
return hb_arrayGetL(pArray_RESTORE, i);
case ID_MAXIMIZE:
return hb_arrayGetL(pArray_MAXIMIZE, i);
case ID_MINIMIZE:
return hb_arrayGetL(pArray_MINIMIZE, i);
case ID_CLOSE:
return hb_arrayGetL(pArray_CLOSE, i);
default:
return FALSE;
}
}
}
return FALSE;
}
HB_FUNC (IS_CHECK_ARRAY)
{ hb_retl (CheckArray ((HWND) hb_parnl (1), hb_parni (2)));
}
LONG GetArray_Old_WndProc (HWND hWnd)
{ int i;
// Busca la ventana y devuelve el WndProc original
for (i=1; i <= cont; i++)
{ if ((HWND) hb_arrayGetNL (pArray_HWND, i) == hWnd)
return (LONG) hb_arrayGetNL (pArray_Old_WndProc, i);
}
return NULL;
}
LRESULT CALLBACK WndProc_PIRATA (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_SYSCOMMAND)
{
if ((wParam & 0xFFF0) == SC_MOVE && CheckArray (hWnd, ID_MOVE))
return 0;
if ((wParam & 0xFFF0) == SC_SIZE && CheckArray (hWnd, ID_SIZE))
return 0;
if ((wParam & 0xFFF0) == SC_RESTORE && CheckArray (hWnd, ID_RESTORE))
return 0;
if ((wParam & 0xFFF0) == SC_MAXIMIZE && CheckArray (hWnd, ID_MAXIMIZE))
return 0;
if ((wParam & 0xFFF0) == SC_MINIMIZE && CheckArray (hWnd, ID_MINIMIZE))
return 0;
if ((wParam & 0xFFF0) == SC_CLOSE && CheckArray (hWnd, ID_CLOSE))
return 0;
}
p_WndProc_old = (WNDPROC) GetArray_Old_WndProc (hWnd);
return CallWindowProc(p_WndProc_old, hWnd, message, wParam, lParam);
}
#pragma enddump