[C con Clase] consulta

Steven Davidson srd4121 en njit.edu
Jue Oct 20 23:24:55 CEST 2011


Hola Santiago,

2011/10/20 Santiago Tabarez <santiago230792 en gmail.com>:
> Antes que todo, agradezco la ayuda. Ahora, tego otras cuestiones acerca del
> proyecto de una barra de estado y demás:
>

Veámoslas.

> 1. Incluí las mejoras que habías sugerido. Pero a la hora de compilar, la
> funcion InitCommonControlsEx(), y la estuctura INITCOMMONCONTROLSEX me daban
> errores, por lo que tuve que redefinirlas. No me produjo un error cargar
> InitCommonControls() por sí misma, aunque fuera mas antigua.
> Me aparecian otros errores con las funciones:
>     DefSubclassProc(...)
>     SetWindowSubclass(...)
>     RemoveWindowSubclass(...)
> entonces las redefiní, evitando los errores.
> Pero cuando logré compilar con exito el programa persistía el problema: no
> fucinaba el boton de la barra de estado.
> ¿será que el IDE/compilador que uso está desactualizado u obsoleto? Lo probé
> en Dev-Cpp y en Code::Blocks.
>

En primer lugar, NUNCA redefinas funciones que formen parte de un API.
Si el compilador te lanza errores, es por una razón muy buena.

En segundo lugar, tienes algunos errores:

- #defines las constantes que te mencioné para MS-Windows XP después
de incluir <windows.h>; sería demasiado tarde. Debes definir estas
constantes simbólicas antes de incluir <windows.h>, para que este
fichero de cabecera defina esas estructuras y funciones. Esto es,

#define _WIN32_WINNT        0x0501
#define _WIN32_IE           0x0501
#include <windows.h>
#include <commctrl.h>

- En 'WinMain()', invocas 'InitCommonControlsEx()' sin parámetros. Por
lo que veo, esto proviene de algún intento que hiciste después de lo
que te comenté. Elimina esta invocación errónea y elimina los
comentarios para que vuelva a aparecer la siguiente sentencia:

if( !InitCommonControlsEx(&iccex) )
  return 0;

Aún así, vas a seguir teniendo un problema, porque el enlazador se
quejará al no tener las implementaciones de estas funciones. Esto es
porque debes enlazar la biblioteca simbólica de "comctl32.lib" o en tu
caso, "libcomctl32.a" ya que seguramente usas el compilador de MinGW
con Dev-C++ y Code::Blocks. Tienes que configurar tu proyecto para
indicar al enlazador este fichero. Bajo Code::Blocks,
1. Elige en el menú, Project->Build Options...
2. Elige la pestaña, "Linker settings"
3. En el recuadro de edición bajo el título "Other linker options",
escribe: "-lcomctl32"  (sin las comillas).
4. Pulsa el botón de "OK"
5. Reconstruye tu proyecto: Build->Rebuild

> 2.  Acerca de la ayuda en Windows, ¿la función
> WinHelp(HWND,LPCSTR,UINT,DWORD) está obsoleta? Por lo menos, en Windows 7,

No. No está obsoleta, pero sí está en fase de quedarse obsoleta, por
lo que se debería usar otros formatos de ayuda como ".chm", ".html", o
".xml". Además hay funciones para leer estos formatos en el API, como
'HtmlHelp()'.

> parece que cambió el formato de ayuda. Probé con ese mismo formato (tomé una
> copia de un arhivo de ayuda de Windows 7), pero con la función WinHelp, pero
> Windows me seguía devolviendo un mensaje :
>
>> La Ayuda de este programa se creó con el formato de Ayuda de Windows, que
>> depende de una característica que no está incluida en esta versión de
>> Windows. Sin embargo, puede descargar un programa que le permitirá ver los
>> archivos de Ayuda creados con el formato de Ayuda de Windows...
>
>
> Tal vez ésta función ya no es útil en Windows 7.
>

La función 'WinHelp()' simplemente ejecuta el programa "winhelp.exe"
para los ficheros ".hlp" de 16 bits de versiones anteriores. Sin
embargo, como dice el mensaje, que te envía el sistema operativo,
MS-Windows 7 - y también Vista - ya no traen el programa de
"WinHlp32.exe" - la versión de 32 bits de ".hlp" - en la instalación
común de estos sistemas operativos. Eso sí, se puede descargar
directamente desde la página de MS-Windows, por si lo requieres.

> 3. ¿Es posible crear una barra de herramientas con la función
> CreateToolbarEx(HWND,DWORD,UINT,int,HINSTANCE,UINT,LPCTBBUTTON,int,int,int,int,int,UINT)
> (ubicada en commctrl.h)?
> No se si podrías explicarme la sintaxis de esta funcion.
>

No sé si es esto lo que quieres, pero el control de una barra de
herramientas es un grupo de botones ubicados en horizontal o en
vertical. Es posible agregar otros tipos de controles que no sean
botones, pero necesitas controlar explícitamente esos controles, ya
que este control de la barra de herramientas sólo entiende de botones.
Para esto, deberías usar el control de la barra de refuerzo ("rebar",
en inglés). También puedes "meter" la barra de herramientas en la
barra de refuerzo, que es lo que hace muchos de los navegadores web,
como Internet Explorer.

En cuanto a esta función, no la uses porque está en fase de quedarse
obsoleta. En su lugar, usa 'CreateWindowEx()' con la clase
'TOOLBARCLASSNAME'.

> 4. ¿existen otras clases aparte de las ya conocidas "edit", "button",
> "scrollbar", etc?

Estos controles son los comunes que todas las versiones de MS-Windows
traen y se consideran parte del API de MS-Windows. Los nuevos
controles provienen de "comctl32.dll", que originalmente venía con
cada versión de Internet Explorer. Tendrías que mirar tu versión de
MS-Windows (y la de IE) para ver cuáles controles están disponibles.
Puedes echar un vistazo a MSDN acerca de los controles disponibles. El
enlace que te interesa es éste:
http://msdn.microsoft.com/en-us/library/bb773169(v=VS.85).aspx

> ¿se pueden crear unas propias?
>

Sí, claro. Al fin y al cabo, un control no es más que una ventana, y
cada vez que creas una ventana, previamente debes crear una clase que
debes registrar.


Por cierto, he mirado por encima el código fuente que nos envías, y
veo que tienes algunos errores en 'WindowProcedure()'. Escribes al
comienzo:

HMENU hmenu = LoadMenu(hInstance, "context");
HFONT hfont;
HWND hButt1, hButt2;

Esto no es aconsejable, porque perderás la información original de
estas variables locales. Recuerda que 'WindowProcedure()' es invocada
muchísimas veces. Esto significa que las variables anteriores son
creadas al comienzo de una invocación a 'WindowProcedure()' y
destruidas al terminar, para volver a ser recreadas en otra invocación
y de vuelta a ser destruidas. Esto implica que estas variables no
contendrán la información válida después de la primera invocación de
'WindowProcedure()'. Por esta razón, se definen estas variables
locales como estáticas, para que no sean destruidas ni recreadas, por
motivos de las invocaciones de 'WindowProcedure()'. Esto es,

static HMENU hmenu = LoadMenu(hInstance, "context");
static HFONT hfont;
static HWND hButt1, hButt2;

Tampoco aconsejo usar variables globales si puedes evitarlas. Entiendo
que estás haciendo pruebas, pero no recomiendo mal acostumbrarse a
ello.

También veo que invocas 'WinExec()'. Esta función está en fase de
quedarse obsoleta, por lo que no se recomienda usarla. En su lugar,
deberías invocar 'CreateProcess()'. Es un poco más complicada de usar,
pero tiene mayor seguridad.


Espero que todo esto te aclare un poco todo este tema.

Steven




Más información sobre la lista de distribución Cconclase