jueves, 5 de enero de 2006

Menú Nk reportándose :->

¡No puedo creerlo!

No le he puesto título al post, no sé qué pensar... qué hacer.

Vengo de revolcarme en el mueble tomado de los cabellos y pujar "ggggg" con una especie de chillido; mis músculos hicieron mucha fuerza, como si todo mi ser fuera a estallar.

Tiemblo, me manoseo los cabellos, todavía tengo la imagen en mi mente: hacía click en un CommandButton1 que creé hace 1 minuto y veía en el frmMain aparecer los menú de prueba que había creado.

Bien, la cosa es así:

Después de que escribí el post pasado hace (creo) no menos de media hora, seguí viendo mi código y pensando en cuál podía ser la función API para hacer aparecer mi barra de menús. Se me vino a la mente el que pudiera ser una función de entrada, digamos, una forma de crear el primer menú, pero no fue así.

Me pasé a la ventana de MSDN y di un vistazo a todas las "Menu Functions" hasta que vi una nada fuera de lo normal: SetMenu. Accedí a su descripción buscando datos en "Remark" que encontré:

"The window is redrawn to reflect the menu change.



The SetMenu function replaces the previous menu, if any, but it does  not destroy it. An application should call the DestroyMenu function to  accomplish this task."

"Uhmmm...", pensé y medio balbuceé. Entonces mi linea "   Call DrawMenuBar (hWnd)" no está mal, y si se supone que mi código para los menús está bien creado, significa que el problema no era eso, sino que mi Barra no se dibujaba... ¡lo que vengo diciéndome y escribiendo desde hace días! Pero aun así me sonó una explicación tonta, tan tonta como las explicaciones que me han llevado a quedarme desvelado y avanzar, así que hice un experimento:

Mi procedimiento para crear los menús está en el módulo modMenú.bas, como ya había dicho, y como mi proyecto inicia en SubMain para llamar al procedimiento del modMenú antes de crear el formulario, entonces pensé que quizá todo eso pasaba y no se dibujaba en el formulario. Creé un botón de comando Command1 en donde cayera (encima del RichTextBox) y en su evento _Click() le puse "Call DrawMenuBar(hWnd)". Lo ejecuté pero no sirvió, además, ¿por qué habría de servir, si tengo esa linea al final de otras en el evento _Resize()?

Bueno, no sirvió, pero de repente me surgió una idea algo más extravagante: Volver a llamar al procedimiento pero ya cuando esté pintado el Form, y para aplicar eso del reciclaje, pues usé el mismo botón de comando. El código quedó:

Private Sub Command1_Click()
Call Crear_Menús_Estándar
End Sub


(Lo hice a la carrera, pero así de desordenado con mis códigos no soy). Ejecuto y ¡oh sorpresa! Aparece mi menú "Nk" y sus submenús "a1" y "b1".

Sin pensarlo me levanté tieso de la silla y me fui al mueble a revolcar. Después de eso vine aquí, pero ahora vamos a testearlo y a escribir en el blog los apuntes, como todo un científico xD, y para que sepan que todo lo que anoto ocurre en tiempo real. (Lo guardo antes que nada :P).

¿Qué ocurre al hacer click en Command1?

Antes tenía una ToolBar llamada "Barra_de_Herramientas", pero por sospechas la cambié a un Label llamado igual. Pues bien, al crearse el menú, el Label y el RichTextBox se hacen un tantito pa'bajo y se crea el menú "Nk".

¿Qué ocurre su presiono más de una vez el Command1?
No aparecen más barras de menús ni menús, sino que, acorde con el texto citado de MSDN, la barra es redibujada en su mismo lugar, pero sin destruir las otras, que quedan invisibles e inabilitadas.

¿Qué ocurre si borramos el Label y reestablecemos nuevamente la ToolBar que tenía?
Veamos...Lo mismo: se hace para abajo.

Ahora tendré que buscar la forma de que se dibuje esa barra sin necesidad de oprimir el botón y haciendo lo posible por mantenerla en el procedimiento Main.

Comienzo a las 3:05 am...

3:09 am: pasé Call SetMenu(hWnd, hMenú) hasta abajo de SubMain, después de hacer el frmMain.Visible = True; para eso tuve que cambiar hMenú de Dim a Public en modMenú.bas

Por el momento eso es todo. Les voy a mostrar mi código en modMenú.bas:

'Handle de la Barra de Menús
Public hMenú As Long

'Handle para los Submenús
Dim hPopupMenu As Long
Private Function Crear_Menú(ByVal Valor As String, ByVal Tipo As mnuTipo, _
                           Máscara As mnuMáscara, Estado_Inicial As mnuEstado, _
                           ByVal Menú_Matriz As Long, ByVal Submenús As Long, _
                           Optional ByVal Posición As Long) As Long

  Dim Información_del_Menú As MENUITEMINFO

  With Información_del_Menú
       .cbSize = LenB(Información_del_Menú)
       .cch = Len(Valor)
       .dwTypeData = Valor
       .fMask = Máscara
       .fState = Estado_Inicial
       .fType = Tipo
       .hSubMenu = Submenús
  End With

  If Posición >= 0 Then Posición = GetMenuItemCount(Menú_Matriz) + 1

  Crear_Menú = InsertMenuItem(Menú_Matriz, Posición, True, Información_del_Menú)

  Call DrawMenuBar(hWnd)

End Function

Public Sub Crear_Menús_Estándar()
   
   hMenú = CreateMenu
   hPopupMenu = CreatePopupMenu
   
   Call Crear_Menú("a1", MFT_STRING, MIIM_TYPE, MFS_DEFAULT, hPopupMenu, vbNull)
   Call Crear_Menú("a2", MFT_STRING, MIIM_TYPE, MFS_DEFAULT, hPopupMenu, vbNull)
   Call Crear_Menú("Nk", MFT_STRING, MIIM_TYPE + MIIM_SUBMENU, MFS_DEFAULT, hMenú, hPopupMenu)
   
End Sub



No incluye declaraciones, ni tipos, ni nada más porque harían un buen de espacio.
Y en el SubMain de modMain.bas:

'Inicializar Menús
   Crear_Menús_Estándar
     
   'Y, después de un gran movimiento por parte del personal, abrimos el telón...
   frmMain.Visible = True
   
   'Haremos que aparezca la Barra de Menús
   Call SetMenu(hWnd, hMenú)


y en frmMain:

Private Sub Form_Resize()
   
   On Error Resume Next
   
   With Área_de_Trabajo
        .Top = Barra_de_Herramientas.Top + Barra_de_Herramientas.Height
        .Left = 0
        .Height = Me.Height - .Top - 1100
        .Width = Me.Width - 100
   End With
   
   Call DrawMenuBar(hWnd)
   
End Sub


Evidentemente esto no es todo. Ya resuelto este problema me creo capaz de editarlos, crear, esconder, darles valores, y lo del evento Click supongo que no será mucha lata, si a casi una desvelada como máximo (que me tarde muchísimo).

También falta perfeccionar mi código: haré que mi función de Crear_Menú() devuelva el ID del menú creado y no el valor Booleano de la API de si se pudo o no crear. También haré otro hPopupMenú_secundario o algo así para lo de "Archivo/Nuevo/Documento en blanco" y otras cosas por el estilo. Pero eso será mañana porque, me apena decirlo, me toca estudiar álgebra.

También voy a jugar Mythology hasta que amanezca y trataré de hacer actividades algo pesadas durante el día para mantenerme despierto (haber si puedo).

Lo que dije entre la primera y segunda desvelada lo sostengo ahora con más ahinco: crear menús con APIs no es difícil, lo que cuesta es descubrir la forma.

Hilsen



PD: Disculpen por las irregularidades del código pero en la edición no puedo empezar líneas con espacios; bueno, sí, pero eso requiere de un esfuerzo que por ahora no estoy dispuesto a realizar.




Editado Viernes 29 de Junio del 2007: Ya le corregí los aspectos del código haciéndolo más legible.

CreatePopupMenu

Con respecto a lo de los menús, hice las siguientes búsqueda en Google:

"crear menú"+"Visual Basic"
"hMenú"+"Visual Basic"
"InsertMenuItem"+"Visual Basic"
"InsertMenuItem"+"Visual Basic"
"menú"+"Visual Basic"
"SetMenu"+"Visual Basic"

No todas tienen los parámetros, algunas están en inglés y otras en español. Pero de todo eso lo único que me sirvió fue esto:

Colabora: API menús por Jordi Garcia

De ahí en fuera todo fueron o bien cosas inútiles o bien cosas inútiles. E inclusive del enlace de arriba debo decir que sólo saqué lo que me servía, puesto que el código era para VB3 me parece, y ahí usaban la API AppendMenu que requiere de no más que 4 parámetros, mientras que mi InsertMenuItem depende de 3 y un tipo de 11 variables. Lo que saqué de ahí fue el empleo de CreatePopupMenu para crear los submenús (digamos, "Abrir, Guardar, Nuevo...").

Me extraña no haber encontrado el enlace ese porque hace media semana que andaba en lo de las desveladas me metí a ElGuille a buscar sobre los menús pero no encontré nada.

En pocas palabras: ya puedo crear un menú Archivo y sus submenús, es más, al decir esto me refiero a que incusive puedo crear menús desplegables como "Archivo/Nuevo/Hoja en blanco"; y se supone que con eso tengo, ¿no? Pues aun sigo sin poder hacer que aparezca mi barra de menús: la tengo que crear desde el Editor de Menús y cambiar un par de líneas en mi código para que aparezca y se creen mis menús de prueba, pero a pura API no aparece, y lo hago igual al código de ElGuille (claro, con sus respectivas modificaciones y ajustes a mi código).

Pero ya tengo más abiertos los horizontes, ahora tengo que pensar en cómo hacer para que aparezca mi barra de menús.

Hilsen

miércoles, 4 de enero de 2006

Eich of Mitzololly

(No sé qué pretendía en el post pasado con ese título de a versito).

Creo que tantos juegos en el Mythology me han dado algo de práctica. Antes la máquina me ganaba siempre... 'por un poquito'. Cuando yo estaba comenzando a crear soldados, ella ya venía con su ejército, y cuando yo seguía con mi MONOSeattlement, ella ya abarcaba dos Seattlement e iba por el tercero; siempre me ganaba por poco en todo, pero me ganaba.

Ahora creo que he descubierto la base para una buena economía en el nivel Moderado: irse con los dos o tres aldeanos (o enanos xD) a crear un granero por donde haya esas cosas como brócoli gigantes y gastarse toda la comida en aldeanos para llevarlos a recoger a esos arbustos (hasta ahora, la táctica que llevaba haciendo desde hace ya tiempo.

Pero he aquí la diferencia: yo mandaba a los otros sujetos a recoger comida y luego creaba otros dos o tres (con la comida que recien había acumulado) para recoger madera y oro y construir mis casas y el templo, pero sucede que para una buena economía necesito gente que esté trabaje y trabaje todo el tiempo, más con los egipcios que fueron hechos para construir. Entonces, lo que tengo que hacer es mandar a todos a recoger esos arbustos, coger la carne de las cabras, cerdos y vacas y gallinas, y uno que construya una casa, lo que sea para recoger madera y el templo y luego siguiera consiguiendo comida, mientras mando a mi Ulfsark/Katáskopos/Priest a peinar la zona en busca de comida.

Haciendo eso, en unos minutos se puede obtener hasta 800 y pico de comida, como yo lo hice, dejaba en la cola del centro urbano unos cuatro o cinco aldeanos y el avance a la edad Clásica.

Evidentemente la máquina llegaba a la clásica antes que yo, pero con mis aldeanos nuevos y los otros que ya había terminado la comida, me ponía a talar árboles y recoger oro y a cazar ciervos, caribúes, hipopótamos, elefantes o lo que sea, el caso es tener a 7 o más recolectando comida y a seis con oro y con la madera, los que sean necesarios, puesto que con la madera no le veo tarifa fija (los egipcios necesitan más oro, mientras que los griegos y vikingos, madera).

En todo lo que avanza de edad hay que poner a todos los aldeanos a trabajar y crear un héroe para que recoga las reliquias (en el caso de los Egyptian, el Faraón lo puede hacer desde el principio).

Al avanzar de edad, hay que crear otros cinco aldeanos e irles asignando las tareas necesarias (6 en oro, 7 o más en comida y los que sobren (que sean como 5 (sino créalos)) en madera). Mandar a uno o dos para que creen casas, la herrería y tres cuarteles (Long houses, Barraks(o algo así) o lo que sea que se parezca a un cuartel para entrenar milicias).

Hasta ahora llevaríamos unos 600 de cada cosa como mínimo. Pues en todo lo que el o los aldeanos construyen, creamos al héroe de la Clásica con la madera que hemos acumulado (todos los héroes de la clásica (creo) cuestan siempre 200 de madera y 2 de fé).

Ya tenemos nuestros dos héroes, casi 1000 de cada uno y tres cuarteles en creación. El siguiente paso es crear unos aldeanos y mandarlos a cultivar en granjas; para cuando estén ya arando tendremos los tres cuarteles listos y el Seattlement rodeado de granjas, lo que hacemos es seleccionar nuestros tres cuarteles a la vez (doble click en uno (tienen que estar cerca)) y darle cinco veces al muñequito de la izquierda, el primero, porque creo que es el que resulta ser más fuerte; de este modo estarán en cola 15 soldaditos, 5 en cada cuartel, nos vamos al templo y creamos una unidad mitológica. Si no te alcanza para la unidad mitológica es porque vas mal de economía y puede que ese sea el único ejército que puedas tener en la partida, a menos que la unidad requiera de madera, como los centauros, ahí sí puedes ser perdonado :P.

Con la comida que nos sobre, vemos si podemos crear unos 5 aldeanos, para mandarlos a la comida o madera, y, según especulo yo, tendrás suficientes recursos para desarrollar los tres (o cuatro) implementos visibles de la herrería.

Mandas tus unidades al ataque. No sé qué vayas a atacar, pero yo me voy por el cuartel y el templo que seguramente tendrán y cuando se destruyen, dejo que los muñequitos peleen automáticamente. Con esto ya tendrás bloqueada la economía de la compu y suficientes recursos (al rededor de mil de comida u oro) para otra ronda de 15 soldaditos y una unidad mitológica.

Para esto ya debes tener tu centro urbano rodeado de granjas y otro molino aparte también rodeado de granjas.

Todos los avances tanto de los centros madereros y de oro deben estar avanzados, en el caso de los molinos basta con encargarse de los de la granja. Los de la herrería nunca deben olvidarse.

Así nos vamos hasta que poco a poco la compu se queda sin edificios militarea, luego guerreros, luego aldeanos, luego el Seattlement y luego sus casitas hasta que sale su letrero de "May I offer my surrender?", o "Can we stop this war before haya más gente lastimada"? y pues, si se trata de Griegos o Egipcios, le digo que sí, porque somos civilizados y hay que tomar buenas desiciones para nuestro pueblo, pero si estoy con los Vikingos, que se vayan mucho a talar árboles porque los voy a asesinar a todos.

Cuando estoy con los vikingos y me ofrecen su rendición, les digo que no pero dejo de crear unidades y trato de alejar ese ejército, conquisto los Seattlements que queden y me dedico a juntar oro y todo para desarrollar la omniprescencia y luego crear una maravilla.

Lo que ocurría antes que aplazaba mis avances era porque, apenas y tenía recursos suficientes, avanzaba de edad, y al estar en la heróica, creaba un centro urbano y un mercado en la esquina contraria para hacer unos 10 o 15 animales que comerciaran con una buena feria, y con eso perdía mis pocos recursos y la máquina me embestía.

Pero ahora cuando gano generalmente estoy desarrollando o por desarrollar la Edad Heróica, con no más que un Seattlement, sin mercado y sin Fortress, o Migdol Stronghold o Fortress Hil.

Se dan casos en que la máquina me gana: no sé por qué. Pero cuando veo que me están atacando y no tengo ni estoy creando ningún ejército, le doy "Resign" para ver qué tan avanzada va la máquina.

Yo uso los poderes de dioses para ayudarme: el de Bronze lo utilizo cuando tengo un numeroso ejército y deseo atacar un centro urbano, el de la Pestilencia puede ser usado desde que llegas a la edad Clásica: mandas a tu explorador o algo al reino enemigo y cuando esté a la vista el Seattlement, le das la Pestilencia para que no cree unidades; el templo podrá estar cerca y con suerte tampoco le tocará nada; si hay un cuartel entonces apúrate a recoger recursos.

Voy a buscar info sobre los menús y luego a jugar Mythology.

Hilsen

En busca de una luciérnaga en la ciénaga

He regresado de vacaciones. Me la he pasado medianamente bien.

En el post anterior estaba tan urgido por terminar que se me pasó contar un detalle acerca de los menús: logré ver que, teniendo ya creados X menús con el Editor de Menús, puedo ver en la ventana de propiedades las respectivas propiedades de ellos: caption, name, etc. De hecho, ya había visto antes que se agregaban en la ventana de propiedades, pero nunca le puse atención a ese detalle puesto que cuando necesitaba componer algo en mis menús iba directamente al Editor de Menús. El caso es que todo el tiempo se me olvidó que los menús se podían manipular muy bien ahí.

Cuando me di cuenta de eso, mi cara quedó paralizada y mi mente se nubló de incredulidad. Estaba perplejo viendo aquellas propiedades enlistadas: cada menú tenía su propia zona en aquella ventana.

Pensé que sería mejor, más fácil y que además me ahorraría mucho código el manipular a través de ahí a mis menús, ya que lo que quiero no pasa de cambiar el Caption de cada uno a mi gusto es por eso de la compatibilidad de idiomas de la NekroLicencia); pero luego pensé en que me había matado varias noches aprendiendo a usar esas APIs e inclusive había faltado al sueño dos veces (en año nuevo ocurrió la tercera) com pequeños avances: la tecnología cuesta menos coronas que sudor.

Después de rápidamente tomar esa desición, seguí con lo de las APIs pero sin lograr nada. Mi teoría sigue en pie: la razón por la que mis menús no se dibujan en el form a pesar de estar ya creados y asignados a la ventana es porque me hace falta poner ese código para crear eventos: ¿cómo hago para definir las acciones que ocurrirán cuando le de click a un menú?

Creo que necesito crear una clase y ponerle el Event Click, pero al crear esa clase me vería en la necesidad de crear los menús para allá y, ¿cómo saber, en el .cls, cuando se hace click en un menú creado con APIs? Había pensado en un GetMessage, pero tendría que andarlo checando con un Timer o algo cada ratito para ver si alguien ha hecho un click y eso sería usar mucho espacio.

En eso me la paso pensando: mi barra de menú está creada, junto con sus items, pero, ¿cómo saber cuando se ha hecho click en un menú?; al responder esta pregunta creo que el código para que aparezcan vendría sólo.

Creo que voy a buscar sources donde vengan menús creados con APIs, a ver qué loco ya lo hizo, pero me sentiría defraudado al pensar que alguien sí lo hizo sin ayuda de otro, por eso es que flaqueo al imaginarme buscando en Google.

Pero mientras no, voy a investigar con las APIs y quizá relea algo sobre clases para ver si encuentro algo que me pueda ser de utilidad para establecer el _Click() o dibujar los menuseses.

Hilsen