Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Eleкtro

#271
Versión 3.1:

    AdvancedAutoConcede.dll:
    Fixed an issue in which the number of remaining automatic concedes in the log was not displayed correctly.

    BattleTagCrawler.dll:
    Fixed an issue in which battletags were crawled outside the hour range specified in the plugin configuration window.

    SystemTrayIcon.dll, TaskBarInformer.dll and WindowRestorator.dll:
    All of these three plugins and its features has been joined into a new, single assembly: UIEnhancer.dll

    (So you must manually delete the old assemblies from your plugins directory, in order to avoid possible conflicts.)

    Other Changes:
    Updated the versions of SBAPI.dll, HearthMirror.dll and HearthWatcher.dll assemblies.
#272
Según la documentación de Microsoft:

   WebBrowser.Navigating event:
       Occurs before the WebBrowser control navigates to a new document

   WebBrowser.Navigated event:
       Occurs when the WebBrowser control has navigated to a new document and has begun loading it.
       ...
       Handle the DocumentCompleted event to receive notification when the WebBrowser control finishes loading the new document.

   WebBrowser.DocumentCompleted event:
       Occurs when the WebBrowser control finishes loading a document
       ...
       Handle the DocumentCompleted event to receive notification when the new document finishes loading. When the DocumentCompleted event occurs, the new document is fully loaded

En resumen, el orden de desencadenamiento de eventos es el sigueinte:

1. WebBrowser.Navigating: cuando comienza la navegación a "X" url.
2. WebBrowser.Navigated: cuando comienza la carga del documento html en la página a navegar.
3. WebBrowser.DocumentCompleted: cuando finaliza la carga del documento html en la página a navegar.

Como no hay tiempo suficiente para que comience la carga del documento html en el ejemplo de código que compartí más arriba, el evento Navigating se dispara para todas las urls, mientras que el evento Navigated se dispara solamente para la última url como puedes comprobar en la imagen que compartí. Si quieres obtener la url de todas las redirecciones antes de que comience la carga del documento para validar/filtrar la url y poder cancelar la navegación o lo que pretendas hacer, entonces deberías seguir usando el evento Navigating como en el ejemplo de código que mostré.




Cita de: PotatoWith en 12 Agosto 2019, 01:05 AMYa probe un WebBrowser.DocumentCompleted y sigue apareciendo muchas veces el link en mi consola

Para serte sincero, no tengo un gran domino en cosas relacionadas con la programación a nivel web, cosas de html y de páginas web en general, de hecho, de vez en cuando a mi también me surjen algunas dudas con ciertos aspectos del componente WebBrowser. Lo que puedo decirte es que el evento DocumentCompleted puede dispararse múltiples veces, ya que una página puede contener iframes que desencadenen el evento, pero por otro lado el evento Navigating y Navigated solamente debería dispararse una vez por cada url... ¿pero tu dices que no es así?.

De cualquier manera, siempre existe la solución rudimentaria de declarar una variable booleana para evitar, o mejor dicho ignorar múltiples desencadenamientos del mismo evento. Es decir, la primera vez que se dispare el evento DocumentCompleted, le asignarías un valor True a dicha variable, y si se vuelve a disparar el evento solo tienes que comprobar si el valor de la variable es True o False; de esta forma evitas la repetición de tu "validación de url" por así decirlo donde usas esa condicional para comprobar si la url contiene cierta cadena de texto.

Saludos.
#273
Prueba añadiendo un controlador para el evento WebBrowser.Navigating...

Código (vbnet) [Seleccionar]
Public Class Form1

   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       Dim urls As String() = {"google.co.jp", "google.co.uk", "google.es", "google.com"}
       For Each url As String In urls
           Me.WebBrowser1.Navigate(url)
       Next
   End Sub

   Private Sub WebBrowser1_Navigating(sender As Object, e As WebBrowserNavigatingEventArgs) Handles WebBrowser1.Navigating
       Console.WriteLine($"Starting navigation: {e.Url}")
       Me.ValidateUri(e.Url)
   End Sub

   Private Sub WebBrowser1_Navigated(sender As Object, e As WebBrowserNavigatedEventArgs) Handles WebBrowser1.Navigated
       Console.WriteLine($"Completed navigation: {e.Url}")
   End Sub

   Private Sub ValidateUri(uri As Uri)
       If uri.AbsoluteUri.Contains("PARTE DE MI ENLACE WEB") Then
           ' ...
       End If
   End Sub

End Class




Saludos.
#274
Cita de: Extraterreste en 11 Agosto 2019, 12:34 PMyo de VB se poco

Realmente el código en VB.NET es lo de menos, lo importante es el concepto...

SendMessage y PostMessage en C#:

Conversor offline de código VB.NET a C#:
(mi recomendación personal. puedes encontrar el programa con su "medicina" facilmente)

Conversor online de código VB.NET a C#:
(este puede dar fallos de conversión en comparación con el otro conversor)




Cita de: Extraterreste en 11 Agosto 2019, 12:34 PM
Sí vaya error con mi nick, y ahora no lo puedo arreglar... lástima.

Si que puedes. Haz click aquí si deseas cambiarte el nombre a mostrar:

Saludos
#276
Cita de: 01munrra en  6 Agosto 2019, 16:02 PM
quisiera que se estuviera actualizando los valores en el formulario, pero esto no lo esta haciendo, no refresca los valores mostrados

¿Como esperas que eso ocurra, cuando solamente estás "actualizando" los valores una única vez al finalizar la creación de la ventana del Form en este controlador de evento?:

Citar
Código (vbnet) [Seleccionar]
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
...

Solucion: añade un Timer (pero del tipo System.Windows.Forms.Timer) a ese Form para actualizar los valores de los controles periodicamente...




Le hice algunos cambios al código en general. Prueba así:

SensorClass.vb
Código (vbnet) [Seleccionar]

Imports System.IO.Ports
Imports System.Timers

Public NotInheritable Class SensorClass : Implements IDisposable

#Region "Properties"

   Public ReadOnly Property SerialPort As SerialPort
       Get
           Return Me.serialPort_
       End Get
   End Property
   Private serialPort_ As SerialPort

   Public ReadOnly Property Output As String
       Get
           Return Me.output_
       End Get
   End Property
   Private output_ As String

#End Region

#Region "Private Fields"

   Private WithEvents TimerSensores As Timer

#End Region

#Region "Constructors"

   <DebuggerStepThrough>
   Public Sub New()
       Me.CommPortSetup()

       Me.TimerSensores = New Timer() With {
           .AutoReset = True,
           .Interval = 100,
           .Enabled = True
       }
   End Sub

#End Region

#Region "Private Methods"

   <DebuggerStepThrough>
   Private Sub CommPortSetup()
       Me.serialPort_ = New SerialPort With {
           .PortName = "COM7",
           .BaudRate = 9600,
           .DataBits = 8,
           .StopBits = StopBits.One
       }

       Me.serialPort_.Open()
   End Sub

#End Region

#Region "Event-Handlers"

   <DebuggerStepperBoundary>
   Private Sub TimerSensores_Elapsed(sender As Object, e As ElapsedEventArgs) Handles TimerSensores.Elapsed
       Me.SerialPort.Write("#03A" & ControlChars.Cr)
       Me.SerialPort.DiscardInBuffer()

       Me.output_ = Me.SerialPort.ReadTo(ControlChars.Cr)

       DirectCast(sender, Timer).Interval += 1000
   End Sub

#End Region

#Region "IDisposable Implementation"

   Private disposedValue As Boolean ' Flag to detect redundant calls

   <DebuggerStepThrough>
   Public Sub Dispose() Implements IDisposable.Dispose
       Me.Dispose(disposing:=True)
   End Sub

   <DebuggerStepThrough>
   Private Sub Dispose(disposing As Boolean)
       If Not (Me.disposedValue) AndAlso (disposing) Then
           Me.TimerSensores?.Dispose()
           Me.serialPort_?.Dispose()
       End If

       Me.disposedValue = True
   End Sub

#End Region

End Class


Form1.vb
Código (vbnet) [Seleccionar]
Public Class Form1

   Private sensorClass As SensorClass
   Private canal0_nd03, canal1_nd03, canal2_nd03, canal3_nd03, canal4_nd03, canal5_nd03, canal6_nd03, canal7_nd03 As String

   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       Me.sensorClass = New SensorClass()
     
       With Me.Timer1
           .Interval = 100
           .Enabled = True
           .Start()
       End With
   End Sub

   Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

       Dim output As String = SensorClass.Output
       Me.canal0_nd03 = output.Substring(3, 4)
       Me.canal1_nd03 = output.Substring(10, 4)
       Me.canal2_nd03 = output.Substring(17, 4)
       Me.canal3_nd03 = output.Substring(24, 4)
       Me.canal4_nd03 = output.Substring(31, 4)
       Me.canal5_nd03 = output.Substring(38, 4)
       Me.canal6_nd03 = output.Substring(44, 4)
       Me.canal7_nd03 = output.Substring(52, 4)

       'MOSTRAR DATOS
       Me.Label2.Text = $"{Me.canal0_nd03} ºC"
       Me.Label6.Text = $"{Me.canal1_nd03} ºC"
       Me.Label10.Text = $"{Me.canal2_nd03} ºC"
       Me.Label7.Text = $"{Me.canal3_nd03} ºC"
       Me.Label14.Text = $"{Me.canal4_nd03} ºC"
       Me.Label11.Text = $"{Me.canal5_nd03} ºC"
       Me.Label18.Text = $"{Me.canal6_nd03} ºC"
       Me.Label15.Text = $"{Me.canal7_nd03} ºC"

        '' Si tienes problemas para actualizar el texto de los Labels,
        '' desactiva alguna de las siguientes lineas comentadas para invocar el método de dibujado.
        '
       ' Me.Invalidate(invalidateChildren:=True)
       ' Me.Refresh()

   End Sub

End Class


PD: No puedo comprobar si el código funciona como debería fucnionar, ya que carezco de ese dispositivo que estás utilizando, pero en teoría debería funcionar correctamente. Aparte, no entiendo muy bien por que en el método OnTimer incrementas el intervalo del timer en 1 segundo cada vez que hace tick, pero lo he dejado tal cual en el método TimerSensores_Elapsed.

Saludos.
#277
Puedes utilizar LINQ de la siguiente manera para simplificar el uso de varios búcles/For. De todas formas, todo resultaría más dinámico si en lugar de un ListView adaptases tu código para utilizar un DataGridView enlazando datos de origen en la propiedad DataGridView.DataSource.



Código (vbnet) [Seleccionar]
Public Class Form1

   Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

       Dim columnIndex As Integer = 0

       ' Unión entre las colecciones de elementos de ListView1, ListView2 y ListView3.
       Dim items As ListViewItem() =
           ({Me.ListView1.Items.Cast(Of ListViewItem),
             Me.ListView2.Items.Cast(Of ListViewItem),
             Me.ListView3.Items.Cast(Of ListViewItem)
            }.SelectMany(Function(sequence) sequence)
           ).ToArray()

       ' Agrupación de los elementos mediante pares de clave-valor (clave=texto del elemento, valor=cantidad de repeticiones).
       Dim groups As KeyValuePair(Of String, Integer)() =
           (From item As ListViewItem In items
            Let key As String = item.SubItems(columnIndex).Text
            Order By key Ascending
            Group By key Into keys = Group
            Select New KeyValuePair(Of String, Integer)(key, keys.Count())
           ).ToArray()

       ' Creación de nuevos elementos para añadir en el ListView4.
       Dim newItems As ListViewItem() =
           (From group As KeyValuePair(Of String, Integer) In groups
            Select New ListViewItem({group.Key, CStr(group.Value)})
           ).ToArray()

       ' Adición de los nuevos elementos al ListView4.
       With Me.ListView4
           .BeginUpdate()

           .Items.Clear()
           .Items.AddRange(newItems)

           .EndUpdate()
       End With

   End Sub

End Class


Nótese que en la linea nº 21 del código de arriba, si lo prefieres puedes cambiar el tipo de retorno para devolver un array del tipo ListViewItem directamente.

Saludos.
#278
Cita de: MinusFour en  8 Agosto 2019, 19:39 PM
si tuviera que registrar y proteger una marca hoy en día yo empezaría por encontrar un dominio que está disponible en la mayor cantidad de TLDs.

Gracias por tu opinión.

En esto opino lo mismo que tu, logicamente me gustaría poder adquirir el dominio con más cantidad de dominios de nivel superior o TLDs disponibles, pero empezando por que el dominio .com sea el principal que debe estar disponible. Los demás dominios disponibles serán valiosos, pero tendrán una importancia secundaria para mi. ¿Crees que me equivoco al pensar de esta manera?, lee aquí abajo y entenderás por que pienso así...

Cita de: MinusFour en  8 Agosto 2019, 19:39 PMEs super común que las personas no se acuerden del TLD, ¿Quieres que tus usuarios entren a tudominio.com, cuando tu dominio es tudominio.net? Yo tuve este mismo problema con el foro hace 15 años o más. Siempre acababa en SPAM(3) y luego esa persona se compro elhacker.org.

Precisamente el otro dia quise entrar a Mega para borrar archivos, pero no recordaba el dominio de Mega, y entonces me puse a buscarlo en Google tal cual: "Mega". Tras un intento fallido, empecé a buscar por "Mega.biz", "Mega.zn", "Mega cloud" y términos parecidos, incluso busqué por el antiguo nombre "Megaupload" a ver si por fin me salía la maldita página que yo estaba buscando, pero seguía sin salirme en la primera página de resultados de Google, y recuerdo que eso me hartó MUCHÍSIMO, y me molesté profundamente (con Google, no con Mega), y al final tuve que hacer máyor esfuerzo para encontrar la url correcta en el artículo de Mega en la Wikipedia. En fin, me tiré aprox. entre 2-5 minutos para encontrar la maldita página a pesar de que yo conocía el nombre, pero no me acordaba del TLD, y eso no me gustó NADA. Otras personas habrían desistido al primer o segundo intento y habrían pospuesto la búsqueda "para otro día", estoy seguro.

Si el dominio hubiese sido .com, este problema no me habría sucedido, por ser .com el más común y habitual como ya todos sabemos, y Mega habría obtenido mi visita y mi actividad de usuario en menor tiempo. Creo que los detalles que parecen así de insignificantes son los que mayor importancia tienen a la hora de elegir el dominio .com o .net (u otros).

A todo esto, ¿quien alguna vez en sus inicios no ha entrado por error al "hermano gemelo" de elhacker.net al escribir .com en su lugar, y escribir un guión donde no lo hay?. Es bastante incomodo y confuso cometer ese tipo de errores para terminar accediendo a una página la cual no tenías realmente intención de visitar...

El problema es que todos los buenos nombres con dominio .com ya están pillados por otras compañías, o están siendo revendidos. Por esos motivos tengo tantas dudas.




Cita de: string Manolo en  8 Agosto 2019, 19:12 PM
A mi el marketing se me da muy bien porque una de mis primeras actividades fue el diseño gráfico, diseño de banners, logotipos, y las típicas frases con gancho. Yo uso nombres que llamen la atención por no estar relacionados con lo que se ofrece en el sitio y creo una relación imaginaria basándome en el factor psicológico de como funciona la memoria al enlazar conceptos para recordarlos. Cortos de una sola palabra, con gancho, que suenen bien en varios idiomas y que se recuerden. Hay un montón libres por el estilo, si le hechas inaginación puedes crear un gran impacto y relacionar 2 términos que absolutamente no tienen nada que ver. Por ejemplo está sin comprar fideo.com
Puedes usar la imaginación y diseñar un logotipo de un rayo (por lo de elektro) con un fideo. Entonces todo tendrá "sentido". Parecerá curiosa la asociación para el cliente y recordará el dominio.
Los usuarios van a acceder por primera vez a traves de algún enlace en otro sitio. Todo se basa en que si el sitio les gusta y van a volver a acceder, que puedan entrar de la forma más rápida y sencilla. Esto mejora la valoración y la imagen que se crea en el usuario. Incoscientemente se piensa, que bien va este sitio. Aunque no tenga nada que ver.

No se. Yo no he estudiado esas materias pero es la primera vez que escucho algo semejante; en la mayoría de los videos que he visto por Internet de gente emprendedora que da consejos (ej. el canal de youtube aprendeemprendiendo), creo haber escuchado que es muy importante que el cliente se haga una idea mental de que trata el negocio solo con leer el nombre de la marca, o en este caso con leer la url. Creo que es un razonamiento lógico, por que si un posible cliente lee "fideo,com", se hará expectativas de encontrar algo relacionado con fideos al hacer click, y cuando vea que no es así se podría molestar y no interesarse ni un segundo más en ver de que trata tu negocio, ya que habrás captado su atención en vano y le habrás confundido y quizás decepcionado...

No pongo en duda que como estrategia pueda estar bien para que la gente asocie algo "random" a tu marca, si, como por ejemplo la marca 'Apple', que a pesar de llamarse como una fruta, vende las cosas que vende, pero yo creo que son casos muy excepcionales donde para empezar el comerciante ha iniciado su empresa ofrecido un producto innovador y de mucho valor para el consumidor, y seguidamente la suerte del marketing con millones $$$ de inversión ha estado mucho de su lado a pesar de llevar el nombre de una manzana. Pero para casos más normales, donde uno sabe que no va a innovar, no le encuentro sentido de por que debería seguir una estrageia para que la gente asocie algo "random" con mi negocio, en vez de hacer lo posible para que asocien algo que realmente esté relacionado con dicho negocio, ¿no sería esto mucho más eficiente?. No se, hablando desde mi completa inexperiencia en el marketing digital, a mi me parece algo arriesgado además de innecesario el usar un nombre que no esté relacionado con los productos/servicios que ofrece tu negocio.

Mira, el otro día entré a la página https://codefit.biz/, yo pensé que tendría algo que ver con la informática (por lo de code), pero me sorprendí bastante al ver que se trata de una tienda de ropa deportiva de fitness. Lo veo una gilipollez el nombre para ese tipo de compañía, sinceramente. :S Entiendo que lo de "fit" se refiere a fitness, ¿pero y lo de "code"?, en fin. Me acordaré de esa tienda por el nombre, si, pero no en el buen sentido...

De todas formas por supuesto tendré en cuenta tu opinión, ya que como dije, yo no he estudiado esas cosas y puedo estar errando en mi forma de pensar, y lo consultaré con ciertas personas del sector del marketing digital para poder obtener una segunda opinión.

Saludos.
#279
Cita de: Alejovsq en  7 Agosto 2019, 22:06 PM
Me gustaría llamar al método Form1_KeyPress() desde el método btnIniciar_Click(), no entiendo como podría pasar los argumentos (creo que se les denomina de ¨Control¨) desde ese punto.

Hacer eso carecería de sentido, puesto que estarías llamando a un controlador de evento (método Form1_KeyPress) con datos de evento (clase KeyPressEventArgs) artificiales. Dicho de otra forma, estarías simulando una pulsación del teclado artificial en el Form, y no creo que realmente desees hacer eso...

Cita de: Alejovsq en  7 Agosto 2019, 22:06 PM
Supongo que la solución sería parecida para implementar los métodos del Timer.

En realidad, la solución óptima y sofisticada sería utilizar la clase/componente BackgroundWorker para aplicar el método de invocación asincrónica en los controles de la interfaz de usuario. Pero como te veo con poca experiencia, y como tampoco se si esto que pides es para un trabajo de clase donde te pidan aplicar cosas más basicas, pues aquí tienes un ejemplo donde utilizo prácticas más básicas:



Código (csharp) [Seleccionar]
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApp1 {

    public partial class Form1 : Form {

        private Random RNG = new Random(Environment.TickCount);

        private char nextChar;

        private bool isSuccess;
        private int successCount;
        private int failCount;

        public Form1() {
           this.InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            this.KeyPreview = true;
        }
       
        private void btnIniciar_Click(object sender, EventArgs e) {

            this.Reset();

            Stopwatch watch = new Stopwatch();
            watch.Start();

            while (watch.Elapsed <= TimeSpan.FromSeconds(3)) {
                this.nextChar = this.GeneradorLetra("ABCDEFG".ToCharArray(), this.nextChar);
                this.lblEtiqueta.Text = this.nextChar.ToString();

                while (!((this.isSuccess) || (watch.Elapsed >= TimeSpan.FromSeconds(3)))) {
                    this.LabelStopWatch.Text = (3 - watch.Elapsed.Seconds).ToString();
                    Application.DoEvents();
                }

                if (this.isSuccess) {
                    Thread.Sleep(500);
                    this.successCount += 1;
                } else {
                    this.failCount += 1;
                }
                this.isSuccess = false;

                this.lblEtiqueta.ForeColor = Label.DefaultForeColor;
                this.LabelSuccessful.Text = this.successCount.ToString();
                this.LabelFailed.Text = this.failCount.ToString();

                watch.Restart();
                Thread.CurrentThread.Join(0);
            }

        }

        private void Form1_KeyPress(object sender, KeyPressEventArgs e) {

            if (!(this.isSuccess) && (char.ToLower(this.nextChar) == char.ToLower(e.KeyChar))) {
                this.lblEtiqueta.ForeColor = Color.Green;
                this.isSuccess = true;

            } else {
                this.lblEtiqueta.ForeColor = Color.Red;

            }

        }

        private char GeneradorLetra(char[] charSet, char previousChar) {
            IEnumerable<char> tmpCol = from char c in charSet
                                       where (c != previousChar)
                                       select c;
            return tmpCol.ElementAtOrDefault(this.RNG.Next(0, tmpCol.Count()));
        }

        private void Reset() {
            this.successCount = 0;
            this.failCount = 0;
            this.LabelSuccessful.Text = this.successCount.ToString();
            this.LabelFailed.Text = this.failCount.ToString();
        }
       
    }
}


Código original escrito en VB.NET:
Código (vbnet) [Seleccionar]
Imports System.Threading

Public Class Form1

   Private RNG As New Random(Environment.TickCount)

   Private nextChar As Char

   Private isSuccess As Boolean
   Private successCount As Integer
   Private failCount As Integer

   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       Me.KeyPreview = True
   End Sub

   Private Sub btnIniciar_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnIniciar.Click

       Me.Reset()

       Dim watch As New Stopwatch()
       watch.Start()

       Do While (watch.Elapsed <= TimeSpan.FromSeconds(3))
           Me.nextChar = Me.GeneradorLetra("ABCDEFG".ToCharArray(), Me.nextChar)
           Me.lblEtiqueta.Text = Me.nextChar

           Do Until (Me.isSuccess) OrElse (watch.Elapsed >= TimeSpan.FromSeconds(3))
               Me.LabelStopWatch.Text = CStr(3 - watch.Elapsed.Seconds)
               Application.DoEvents()
           Loop

           If (Me.isSuccess) Then
               Thread.Sleep(500)
               Me.successCount += 1
           Else
               Me.failCount += 1
           End If
           Me.isSuccess = False

           Me.lblEtiqueta.ForeColor = Label.DefaultForeColor
           Me.LabelSuccessful.Text = CStr(Me.successCount)
           Me.LabelFailed.Text = CStr(Me.failCount)

           watch.Restart()
           Thread.CurrentThread.Join(0)
       Loop

   End Sub

   Private Sub Form1_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) Handles Me.KeyPress

       If Not (Me.isSuccess) AndAlso (Char.ToLower(Me.nextChar) = Char.ToLower(e.KeyChar)) Then
           Me.lblEtiqueta.ForeColor = Color.Green
           Me.isSuccess = True

       Else
           Me.lblEtiqueta.ForeColor = Color.Red

       End If

   End Sub

   Private Function GeneradorLetra(charSet As Char(), previousChar As Char) As Char
       Dim tmpCol As IEnumerable(Of Char) = From c As Char In charSet Where (c <> previousChar)
       Return tmpCol(Me.RNG.Next(0, tmpCol.Count))
   End Function

   Private Sub Reset()

       Me.successCount = 0
       Me.failCount = 0
       Me.LabelSuccessful.Text = CStr(Me.successCount)
       Me.LabelFailed.Text = CStr(Me.failCount)

   End Sub

End Class


Puedes trasladar parte del código a un Timer si lo prefieres para evitar el búcle o llamada bloqueante junto a la llamada Application.DoEvents(), pero para ponerte a usar un Timer sería más eficiente que apliques el uso de la clase BackgroundWorker como ya mencioné.

Caracterísiticas del código/programa de arriba:
- Cuando el usuario presiona la tecla que imprime el caracter correcto, se visualiza en verde durante 500 ms y seguidamente se muestra el siguiente caracter.
- Se considera un fallo solamente si la cuenta atrás llega a 0 sin que el usuario haya conseguido presionar la tecla que imprime el caracter correcto, indiferentemente de la cantidad de fallos que el usuario haya tenido durante la cuenta atrás. Dicho de otra forma, se permiten fallos "infinitos" de pulsación de tecla durante la cuenta atrás.
- La aleatoriedad de muestra de caracteres consiste en que el caracter actual nunca se repetirá en la siguiente "prueba", pero si que podrá volver a mostrarse en las "pruebas" posteriores a esta.

Todo esto es así, por que tampoco especificaste como se supone que debe funcionar exactamente el programa. Pero ya con ese código puedes modificarlo para tus requisitos.

Saludos.
#280
Bueno, con el siguiente ejemplo que he desarrollado ya deberías tener por donde continuarlo para satisfacer tus requisitos:



Código (vbnet) [Seleccionar]
Public Class PictureBoxEx : Inherits PictureBox

   Protected isMoving As Boolean ' Flag that determine whether the image is moving.
   Protected ptStart As Point    ' Point where image moving starts.
   Protected ptMove As Point     ' Point where image moving is at.
   Protected ptEnd As Point      ' Point where image moving ends.

   Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
       If (e.Button = MouseButtons.Left) Then
           Me.ptStart = New Point(e.X, e.Y)
           Me.isMoving = True
       End If

       MyBase.OnMouseDown(e)
   End Sub

   Protected Overrides Sub OnMouseUp(e As MouseEventArgs)
       Me.Update()
       Me.isMoving = False
       Me.ptEnd = Me.ptMove

       MyBase.OnMouseUp(e)
   End Sub

   Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
       If (Me.isMoving) AndAlso (Me.Image IsNot Nothing) Then
           Me.ptMove = New Point(Me.ptEnd.X + (e.X - Me.ptStart.X), Me.ptEnd.Y + (e.Y - Me.ptStart.Y))
           Me.Invalidate()
       End If

       MyBase.OnMouseMove(e)
   End Sub

   Protected Overrides Sub OnPaint(pe As PaintEventArgs)
       If (Me.isMoving) AndAlso (Me.Image IsNot Nothing) Then
           With pe.Graphics
               .TranslateTransform(Me.ptMove.X, Me.ptMove.Y)
               .DrawImage(Me.Image, Point.Empty)
           End With
       End If

       MyBase.OnPaint(pe)
   End Sub

End Class


PD: nótese que para el ejemplo de arriba utilizo la imagen especificada en la propiedad PictureBox.Image, pero puedes hacer lo mismo con la imagen de la propiedad PictureBox.BackgroundImage.

Saludos.