Page 1 of 2

CAMBIO RESOLUCION PANTALLA

Posted: Wed Feb 06, 2008 10:31 am
by Manuel Valdenebro
Para cambiar el tamaño de las ventanas a diferentes resoluciones de pantallas, vengo usando aCoor:=GetCoors( GetDesktopWindow() ). Pero a veces, no queda lo bien que debería.

He visto que algunos programadores en Delphi lo que hacen es cambiar directamente la resolución de la pantalla, a través de las funciones del API-WINDOWS EnumDisplayDevices y ChangeDisplaySettings.- ¿Como podría hacerlo desde FWH?

Posted: Wed Feb 06, 2008 5:01 pm
by ADBLANCO
Ya Somos dos con la misma Necesidad, Espero que alguien nos Ayude.

Angel

Posted: Wed Feb 06, 2008 10:15 pm
by horacio
Esta función no la probé pero imagino que es lo que necesitas

#Include "Fivewin.ch"
#Include "dll.ch"
#Include "Struct.ch"

Function ChangeRes(nX,nY,lDireto)
Local CCDEVICENAME := 32
Local CCFORMNAME := 32
Local EWX_LOGOFF := 0
Local EWX_SHUTDOWN := 1
Local EWX_REBOOT := 2
Local EWX_FORCE := 4
Local DM_BITSPERPEL := nHex("40000") // &H40000 // 4*16^4 // 262144
Local DM_PELSWIDTH := nHex("80000") // &H80000 // 8*16^4 // 524288
Local DM_PELSHEIGHT := nHex("100000") // &H100000 // 1*16^5 //1048576
Local CDS_UPDATE := 1 //&H1
Local CDS_TEST := 4 //&H4
Local DISP_SUCCESS := 0
Local DISP_RESTART := 1
Local nOldX := WndWidth(GetDesktopWnd()) // GetSysMetrics(0)
Local nOldY := WndHeight(GetDesktopWnd()) // GetSysMetrics(1)
Local oDevMode
Local uRet
Local cBuffer
Local lDone:=.F.
DEFAULT nX := WndWidth(GetDesktopWnd()),;
nY := WndHeight(GetDesktopWnd()),;
lDireto:=.f.
STRUCT oDevMode
MEMBER cDevName AS STRING LEN CCDEVICENAME
MEMBER nSpecVer AS _INT
MEMBER nDrvVer AS _INT
MEMBER nSize AS _INT
MEMBER nDrvExtra AS _INT
MEMBER nFields AS DWORD
MEMBER nOrientat AS _INT
MEMBER nPaperSiz AS _INT
MEMBER nPaperLen AS _INT
MEMBER nPaperWid AS _INT
MEMBER nScale AS _INT
MEMBER nCopies AS _INT
MEMBER nDefSrc AS _INT
MEMBER nPrnQlty AS _INT
MEMBER nColor AS _INT
MEMBER nDuplex AS _INT
MEMBER nYResolut AS _INT
MEMBER nTTOpt AS _INT
MEMBER nCollate AS _INT
MEMBER cFormName AS STRING LEN CCFORMNAME
MEMBER nUnusePad AS _INT
MEMBER nBitsPPel AS DWORD
MEMBER nPelWidth AS DWORD
MEMBER nPelHeigh AS DWORD
MEMBER nDisFlags AS DWORD
MEMBER nDisFreq AS DWORD
ENDSTRUCT
cBuffer:=oDevMode:cBuffer
uRet := EnumDisplaySettings(0, 0, @cBuffer)
oDevMode:cBuffer:=cBuffer
IF uRet
// Descomente o ultimo parametro se quer trocar as cores, so que nao recomendo pois irá
// reiniciar
oDevMode:nFields := nOr(DM_PELSWIDTH, DM_PELSHEIGHT /* , DM_BITSPERPEL */)
oDevMode:nPelWidth := nX //ScreenWidth
oDevMode:nPelHeight:= nY //ScreenHeight
// Descomente esta linha para trocar as cores so que nao recomendo
* oDevMode:nBitsPPel := 16 //(could be 8, 16, 32 or even 4)
cBuffer:=oDevMode:cBuffer
uRet := ChangeDisplaySettings(@cBuffer, CDS_TEST)
oDevMode:cBuffer:=cBuffer
DO CASE
Case uRet = DISP_RESTART
if MsgYesNo("Deseja reiniciar para aplicar as alteracoes?", "Atencao")
uRet := ExitWindowsEx(EWX_REBOOT, 0)
Endif
Case uRet = DISP_SUCCESS
uRet := ChangeDisplaySettings( @cBuffer, CDS_UPDATE)
lDone:=.T.
if lDireto
oDevMode:nFields := nOr(DM_PELSWIDTH, DM_PELSHEIGHT /* , DM_BITSPERPEL */)
oDevMode:nPelWidth := nOldX //ScreenWidth
oDevMode:nPelHeight:= nOldY //ScreenHeight
cBuffer:=oDevMode:cBuffer
uRet := ChangeDisplaySettings(@cBuffer, CDS_TEST)
oDevMode:cBuffer:=cBuffer
else
if MsgYesNo("Tem certeza desta alteracao?", "Atencao")
else
oDevMode:nFields := nOr(DM_PELSWIDTH, DM_PELSHEIGHT /* , DM_BITSPERPEL */)
oDevMode:nPelWidth := nOldX //ScreenWidth
oDevMode:nPelHeight:= nOldY //ScreenHeight
cBuffer:=oDevMode:cBuffer
uRet := ChangeDisplaySettings(@cBuffer, CDS_TEST)
oDevMode:cBuffer:=cBuffer
endif
endif
otherwise
MsgAlert("Modo nao suportado", "Erro" )
ENDCASE
endif
return lDone

DLL32 FUNCTION EnumDisplaySettings(lpszDeviceName AS DWORD,;
iModeNum AS DWORD, ;
@lpDevMode AS LPSTR) AS BOOL PASCAL;
FROM "EnumDisplaySettingsA" LIB "User32.dll"

DLL32 FUNCTION ChangeDisplaySettings(@lpDevMode AS LPSTR,;
dwFlags AS DWORD) AS DWORD;
FROM "ChangeDisplaySettingsA" LIB "User32.dll"

DLL32 FUNCTION ExitWindowsEx(uFlags AS DWORD,;
dwReserved AS DWORD) AS DWORD PASCAL;
LIB "user32.dll"

Avisame si funcionó
saludos

Posted: Thu Feb 07, 2008 1:02 pm
by ADBLANCO
Horacio, La probé pero me debe faltar alguna librería:

Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: Unresolved external '_HB_FUN_GETDESKTOPWND' referenced from C:\FUENTES\HCM\OBJ32\_RESOL.OBJ


Gracias

P.D. FW 7.09 + XHARBOUR .997

Posted: Thu Feb 07, 2008 1:26 pm
by horacio
Angel: Esta rutina la bajé de Fivewin Brasil. Podrías hacer una consulta porque allí hay un foro y se me ocurre que la misma la escribió un brasilero ( por los comentarios ).

Posted: Thu Feb 07, 2008 2:50 pm
by Antonio Linares
Usa GetDesktopWindow()

Posted: Thu Feb 07, 2008 10:28 pm
by Manuel Valdenebro
Gracias Horacio,

Ademas de la rectificación que dice Antonio (se puesd sustituir por GetSysMetrics(0) y GetSysMetrics(1) ) hay otro pequeño error. Hay que sustiuir todos los nPelHeight por nPelHeigh.

Funcionar, funciona pero mal. Ya que realiza el cambio de resolución de pantalla pero a 256 colores.- Por tanto, todo se ve un poco distorsionado. Seguramente habrá algun parámetro que habrá que cambiar tambien.
Segun un código que he visto en Delphi, en las funciones EnumDisplaySettings y ChangeDisplaySettings repetimos las variables y no coinciden con las funciones de Windows. Quizas algun entendido en "C" pueda ayudarnos un poquito ¿Antonio?

Posted: Thu Feb 07, 2008 10:41 pm
by Antonio Linares
Manuel,

Este valor parece que controla el número de colores:

oDevMode:nBitsPPel := 16 //(could be 8, 16, 32 or even 4)

Posted: Fri Feb 08, 2008 9:38 am
by Manuel Valdenebro
!!! YA ESTA SOLUCIONADO ¡¡¡

En primer lugar comentar que la función original ChangeRes corresponde a los brasileiros Marcelo Gomes y Yuri Marcelino, y se encuentra en el foro de FW-Brasil:

http://www.fivewin.com.br/forum/topic.a ... C_ID=10465

En segundo lugar que en base a dicha función, he elaborado la función CamReso() para xHarbour, que cambia la resolución de la pantalla y automaticamente vuelve a la resolución original al cerrar la aplicación. A mi me funciona perfectamente.

¿Cual es mi método?

1) FUNCTION MAIN()
LOCAL nResoAncho := GetSysMetrics(0)
......
......
IF nResoAncho > 800
IF MSGYESNO("Este programa está diseñado para una resolución de pantalla"+CRLF+;
"de 800 x 600." +CRLF+CRLF+;
"Al estar configurada la resolución de su monitor a una mayor,"+CRLF+;
"verá las ventanas y mensajes bastantes mas pequeños."+CRLF+CRLF+;
"¿DESEA MODIFICAR LA RESOLUCION DE SU PANTALLA?.","NOMBRE DEL PROGRAMA")
CamReso ( 800, 600, .f. )
ENDI
ENDI
....
....

y esta es la función:

///////////////////////////////////////////////////////////////////
/// FUNCION CamReso
/// CAMBIA RESOLUCION DE PANTALLA TEMPORALMENTE
/// Manuel Valdenebro 2008
/// Adaptación ChangeRes() Marcelo Gomes/Yuri Marcelino
/// http://www.fivewin.com.br/forum/topic.a ... C_ID=10465
/// ---------------------------------------
// nAncho ancho pantalla
// nAlto alto pantalla
// lPreguntar si pregunta antes de realizar el cambio
///////////////////////////////////////////////////////////////////

#Include "dll.ch"
#Include "Struct.ch"

Function CamReso(nAncho, nAlto, lPreguntar)
Local DM_PELSWIDTH := nHex("80000")
Local DM_PELSHEIGHT := nHex("100000")
Local oDevMode
Local lPosible
Local cBuffer
Local lCamReso := .f.
DEFAULT nAncho := GetSysMetrics(0), ;
nAlto := GetSysMetrics(1), ;
lPreguntar := .t.

STRUCT oDevMode
MEMBER cDevName AS STRING LEN 32
MEMBER nSpecVer AS WORD
MEMBER nDrvVer AS WORD
MEMBER nSize AS WORD
MEMBER nDrvExtra AS WORD
MEMBER nFields AS DWORD
MEMBER nOrientat AS WORD
MEMBER nPaperSiz AS WORD
MEMBER nPaperLen AS WORD
MEMBER nPaperWid AS WORD
MEMBER nScale AS WORD
MEMBER nCopies AS WORD
MEMBER nDefSrc AS WORD
MEMBER nPrnQlty AS WORD
MEMBER nColor AS WORD
MEMBER nDuplex AS WORD
MEMBER nYResolut AS WORD
MEMBER nTTOpt AS WORD
MEMBER nCollate AS WORD
MEMBER cFormName AS STRING LEN 32
MEMBER nUnusePad AS WORD
MEMBER nBitsPPel AS DWORD
MEMBER nPelWidth AS DWORD
MEMBER nPelHeigh AS DWORD
MEMBER nDisFlags AS DWORD
MEMBER nDisFreq AS DWORD
ENDSTRUCT

cBuffer := oDevMode:cBuffer
// Comprueba si es posible cambiar la resolución
lPosible := EnumDisplaySettings(0, 0, @cBuffer)

// Si es posible cambiar la resolución
IF lPosible
if lPreguntar
if MsgYesNo("Desea cambiar la resolución?", "Atención")
else
RETURN lCamReso
endif
endi
oDevMode:nFields := nOr(DM_PELSWIDTH, DM_PELSHEIGHT )
oDevMode:nPelWidth := nAncho
oDevMode:nPelHeigh := nAlto
cBuffer:=oDevMode:cBuffer
TRY
ChangeDisplaySettings(@cBuffer, 4)
lCamReso := .T.
CATCH
MsgAlert("Modo no soportado", "Error" )
END
else
MsgAlert("Modo no soportado", "Error" )
endif
return lCamReso


DLL32 FUNCTION EnumDisplaySettings(lpszDeviceName AS DWORD,;
iModeNum AS DWORD, ;
@lpDevMode AS LPSTR) AS BOOL PASCAL;
FROM "EnumDisplaySettingsA" LIB "User32.dll"

DLL32 FUNCTION ChangeDisplaySettings(@lpDevMode AS LPSTR,;
dwFlags AS DWORD) AS DWORD;
FROM "ChangeDisplaySettingsA" LIB "User32.dll"

DLL32 FUNCTION ExitWindowsEx(uFlags AS DWORD,;
dwReserved AS DWORD) AS DWORD PASCAL;
LIB "user32.dll"

------------------------------------------------------------

Posted: Fri Feb 08, 2008 10:08 am
by FWHISHOW
Manuel Valdenebro, fiz um teste e usando FWH7.01 + XHARB 99.71 + WINXP, e funcionou, porem aconteceu o seguinte erro depois de trocar a resolução:

HARBOUR EXCEPTION:

CALLED FROM CALLDLL(0)
CALLED FROM CHANGEDISPLAYSETTINGS(0)
CALLED FROM CAMRESO(89)


Grato

Posted: Fri Feb 08, 2008 10:19 am
by yury
En primer lugar comentar que la función original ChangeRes corresponde a los brasileiros Marcelo Gomes y Yuri Marcelino, y se encuentra en el foro de FW-Brasil:
Manuel,

gracias pela citação...

saludos

Posted: Fri Feb 08, 2008 11:49 am
by Manuel Valdenebro
FWHISHOW wrote: HARBOUR EXCEPTION:
CALLED FROM CALLDLL(0)
CALLED FROM CHANGEDISPLAYSETTINGS(0)
CALLED FROM CAMRESO(89)
A mi me funciona perfectamente. Me gustaría saber si otros lo han probado y les funciona.

Posted: Fri Feb 08, 2008 11:50 am
by Manuel Valdenebro
yury wrote: gracias pela citação...
Yury,

Gracias a ti por el trabajo realizado.

Posted: Fri Feb 08, 2008 5:23 pm
by Armando
Manuel:

Probé la función para cambiar la resolución de la pantalla y me tira el "famoso" mensaje de "Se ha detectado un problema y debe cerrarse"
el mensaje aparece inmediatamente despues de hacer el cambio de resolución aunque al tirar el error y cerrar la aplicación vuelve a la resolución anterior.

FWH711 y xHarbour 99.71

Saludos y gracias por la aoportación

Posted: Fri Feb 08, 2008 7:41 pm
by Manuel Valdenebro
Armando wrote:Manuel:"Se ha detectado un problema y debe cerrarse"
¿Puede trabajar bien con xHarbour 99.61 y mal con 99.71?