elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Estamos en la red social de Mastodon


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Vb.net simular presion tecla INSERT
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Vb.net simular presion tecla INSERT  (Leído 3,917 veces)
rapbyone

Desconectado Desconectado

Mensajes: 173


Ver Perfil
Vb.net simular presion tecla INSERT
« en: 15 Febrero 2014, 20:00 pm »

Amigos, estoy en un proyecto personal, les cuento:
Tengo un botón que al presionarlo simula la presión sobre la tecla "Insert" en windows 7 y windows 8 funciona perfecto, pero el windows xp, no me funciona, simplemente la tecla no se presiona.

Este es el código:
Código:
SendKeys.Send("{INSERT}")

No entiendo cual será el problema, ¿se puede lograr de otra manera?


En línea

x64core


Desconectado Desconectado

Mensajes: 1.908


Ver Perfil
Re: Vb.net simular presion tecla INSERT
« Respuesta #1 en: 15 Febrero 2014, 20:10 pm »

Amigos, estoy en un proyecto personal, les cuento:
Tengo un botón que al presionarlo simula la presión sobre la tecla "Insert" en windows 7 y windows 8 funciona perfecto, pero el windows xp, no me funciona, simplemente la tecla no se presiona.

Este es el código:
Código:
SendKeys.Send("{INSERT}")

No entiendo cual será el problema, ¿se puede lograr de otra manera?
Win32: keybd_event


En línea

rapbyone

Desconectado Desconectado

Mensajes: 173


Ver Perfil
Re: Re: Re: Vb.net simular presion tecla INSERT
« Respuesta #2 en: 15 Febrero 2014, 22:49 pm »

Win32: keybd_event

Amigo, podrías aclararme un poco mas como usarlo?
En línea

x64core


Desconectado Desconectado

Mensajes: 1.908


Ver Perfil
Re: Re: Re: Vb.net simular presion tecla INSERT
« Respuesta #3 en: 15 Febrero 2014, 23:01 pm »

Amigo, podrías aclararme un poco mas como usarlo?
Aqui esta la informaciónde la función:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646304(v=vs.85).aspx

Simplemente se llama como cualquier otra función pasandole los parametros correctos.
Puede que te interese además: MapVirtualKey/MapVirtualKeyEx, GetKeyboardLayout. Apesar de eso esta función puede fallar,
así que deberia preguntar: Qué tipo de ventana estaria enviando la tecla? Por eso es que estoy interesado también.
« Última modificación: 17 Febrero 2014, 16:33 pm por Eleкtro » En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.878



Ver Perfil
Re: Vb.net simular presion tecla INSERT
« Respuesta #4 en: 18 Febrero 2014, 08:31 am »

No entiendo cual será el problema

El método SendKeys.Send envía las pulsaciones del teclado a la ventana activa, ¿has tenido eso en cuenta?.

Muestra el código restante, es imposible poder ayudarte sin ver donde cometes el fallo (si hubiera alguno) o como estás usándolo.





De todas formas una alternativa para esta tarea que requieres quizás podría ser usando el método SendInput

He estado haciendo mi implementación de SendInput, todavía está muy verde, no lo he acabado, falta documentación por añadir y mucho código que escribir, y quizás bugs que corregir, pero para lo que tu precisas puedes testear este código.

Modo de empleo:
Código
  1.    Private Sub Test() Handles Button1.Click
  2.  
  3.        AppActivate(Process.GetProcessesByName("notepad").First.Id)
  4.        Dim Result As Integer = SendInputs.SendKeys(Keys.Insert,  BlockInput:=False)
  5.  
  6.        ' Dim Result2 As Integer = SendInputs.SendKey(Convert.ToChar(Keys.Enter))
  7.        ' Dim Result2 As Integer = SendInputs.SendKey("x"c)
  8.  
  9. #If DEBUG Then
  10.        MessageBox.Show(String.Format("Successfull events: {0}", CStr(Result)))
  11. #End If
  12.  
  13.    End Sub

Código
  1. ' ***********************************************************************
  2. ' Author   : Elektro
  3. ' Modified : 02-17-2014
  4. ' ***********************************************************************
  5. ' <copyright file="SendInputs.vb" company="Elektro Studios">
  6. '     Copyright (c) Elektro Studios. All rights reserved.
  7. ' </copyright>
  8. ' ***********************************************************************
  9.  
  10. #Region " Imports "
  11.  
  12. Imports System.Runtime.InteropServices
  13. Imports System.ComponentModel
  14.  
  15. #End Region
  16.  
  17. ''' <summary>
  18. '''
  19. ''' </summary>
  20. Public Class SendInputs
  21.  
  22. #Region " P/Invoke "
  23.  
  24.    Friend Class NativeMethods
  25.  
  26. #Region " Methods "
  27.  
  28.        ''' <summary>
  29.        ''' Blocks keyboard and mouse input events from reaching applications.
  30.        ''' For more info see here:
  31.        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms646290%28v=vs.85%29.aspx
  32.        ''' </summary>
  33.        ''' <param name="fBlockIt">
  34.        ''' The function's purpose.
  35.        ''' If this parameter is 'TRUE', keyboard and mouse input events are blocked.
  36.        ''' If this parameter is 'FALSE', keyboard and mouse events are unblocked.
  37.        ''' </param>
  38.        ''' <returns>
  39.        ''' If the function succeeds, the return value is nonzero.
  40.        ''' If input is already blocked, the return value is zero.
  41.        ''' </returns>
  42.        ''' <remarks>
  43.        ''' Note that only the thread that blocked input can successfully unblock input.
  44.        ''' </remarks>
  45.        <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall,
  46.        SetLastError:=True)>
  47.        Friend Shared Function BlockInput(
  48.               ByVal fBlockIt As Boolean
  49.        ) As Integer
  50.        End Function
  51.  
  52.        ''' <summary>
  53.        ''' Synthesizes keystrokes, mouse motions, and button clicks.
  54.        ''' For more info see here:
  55.        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310%28v=vs.85%29.aspx
  56.        ''' </summary>
  57.        ''' <param name="nInputs">
  58.        ''' Indicates the number of structures in the pInputs array.
  59.        ''' </param>
  60.        ''' <param name="pInputs">
  61.        ''' Indicates an Array of 'INPUT' structures.
  62.        ''' Each structure represents an event to be inserted into the keyboard or mouse input stream.
  63.        ''' </param>
  64.        ''' <param name="cbSize">
  65.        ''' The size, in bytes, of an 'INPUT' structure.
  66.        ''' If 'cbSize' is not the size of an 'INPUT' structure, the function fails.
  67.        ''' </param>
  68.        ''' <returns>
  69.        ''' The function returns the number of events that it successfully
  70.        ''' inserted into the keyboard or mouse input stream.
  71.        ''' If the function returns zero, the input was already blocked by another thread.
  72.        ''' </returns>
  73.        <DllImport("user32.dll", SetLastError:=True)>
  74.        Friend Shared Function SendInput(
  75.               ByVal nInputs As Integer,
  76.               <MarshalAs(UnmanagedType.LPArray), [In]> ByVal pInputs As INPUT(),
  77.               ByVal cbSize As Integer
  78.        ) As Integer
  79.        End Function
  80.  
  81. #End Region
  82.  
  83. #Region " Enumerations "
  84.  
  85.        ''' <summary>
  86.        ''' VirtualKey codes.
  87.        ''' </summary>
  88.        Friend Enum VirtualKeys As Short
  89.  
  90.            ''' <summary>
  91.            ''' The Shift key.
  92.            ''' VK_SHIFT
  93.            ''' </summary>
  94.            SHIFT = &H10S
  95.  
  96.            ''' <summary>
  97.            ''' The DEL key.
  98.            ''' VK_DELETE
  99.            ''' </summary>
  100.            DELETE = 46S
  101.  
  102.            ''' <summary>
  103.            ''' The ENTER key.
  104.            ''' VK_RETURN
  105.            ''' </summary>
  106.            [RETURN] = 13S
  107.  
  108.        End Enum
  109.  
  110.        ''' <summary>
  111.        ''' The type of the input event.
  112.        ''' For more info see here:
  113.        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270%28v=vs.85%29.aspx
  114.        ''' </summary>
  115.        <Description("Enumeration used for 'type' parameter of 'INPUT' structure")>
  116.        Friend Enum InputType As Integer
  117.  
  118.            ''' <summary>
  119.            ''' The event is a mouse event.
  120.            ''' Use the mi structure of the union.
  121.            ''' </summary>
  122.            Mouse = 0
  123.  
  124.            ''' <summary>
  125.            ''' The event is a keyboard event.
  126.            ''' Use the ki structure of the union.
  127.            ''' </summary>
  128.            Keyboard = 1
  129.  
  130.            ''' <summary>
  131.            ''' The event is a hardware event.
  132.            ''' Use the hi structure of the union.
  133.            ''' </summary>
  134.            Hardware = 2
  135.  
  136.        End Enum
  137.  
  138.        ''' <summary>
  139.        ''' Specifies various aspects of a keystroke.
  140.        ''' This member can be certain combinations of the following values.
  141.        ''' For more info see here:
  142.        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms646271%28v=vs.85%29.aspx
  143.        ''' </summary>
  144.        <Description("Enumeration used for 'dwFlags' parameter of 'KEYBDINPUT ' structure")>
  145.        <Flags>
  146.        Friend Enum KeyboardInput_Flags As Integer
  147.  
  148.            ''' <summary>
  149.            ''' If specified, the scan code was preceded by a prefix byte that has the value '0xE0' (224).
  150.            ''' </summary>
  151.            ExtendedKey = &H1
  152.  
  153.            ''' <summary>
  154.            ''' If specified, the key is being pressed.
  155.            ''' </summary>
  156.            KeyDown = &H0
  157.  
  158.            ''' <summary>
  159.            ''' If specified, the key is being released.
  160.            ''' If not specified, the key is being pressed.
  161.            ''' </summary>
  162.            KeyUp = &H2
  163.  
  164.            ''' <summary>
  165.            ''' If specified, 'wScan' identifies the key and 'wVk' is ignored.
  166.            ''' </summary>
  167.            ScanCode = &H8
  168.  
  169.            ''' <summary>
  170.            ''' If specified, the system synthesizes a 'VK_PACKET' keystroke.
  171.            ''' The 'wVk' parameter must be '0'.
  172.            ''' This flag can only be combined with the 'KEYEVENTF_KEYUP' flag.
  173.            ''' </summary>
  174.            Unicode = &H4
  175.  
  176.        End Enum
  177.  
  178. #End Region
  179.  
  180. #Region " Structures "
  181.  
  182.        ''' <summary>
  183.        ''' Used by 'SendInput' function
  184.        ''' to store information for synthesizing input events such as keystrokes, mouse movement, and mouse clicks.
  185.        ''' For more info see here:
  186.        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270%28v=vs.85%29.aspx
  187.        ''' </summary>
  188.        <Description("Structure used for 'INPUT' parameter of 'SendInput' API method")>
  189.        <StructLayout(LayoutKind.Explicit)>
  190.        Friend Structure INPUT
  191.  
  192.            ' ******
  193.            '  NOTE
  194.            ' ******
  195.            ' Field offset for 32 bit machine: 4
  196.            ' Field offset for 64 bit machine: 8
  197.  
  198.            ''' <summary>
  199.            ''' The type of the input event.
  200.            ''' </summary>
  201.            <FieldOffset(0)>
  202.            Public type As InputType
  203.  
  204.            ''' <summary>
  205.            ''' The information about a simulated mouse event.
  206.            ''' </summary>
  207.            <FieldOffset(8)>
  208.            Public mi As MOUSEINPUT
  209.  
  210.            ''' <summary>
  211.            ''' The information about a simulated keyboard event.
  212.            ''' </summary>
  213.            <FieldOffset(8)>
  214.            Public ki As KEYBDINPUT
  215.  
  216.            ''' <summary>
  217.            ''' The information about a simulated hardware event.
  218.            ''' </summary>
  219.            <FieldOffset(8)>
  220.            Public hi As HARDWAREINPUT
  221.  
  222.        End Structure
  223.  
  224.        ''' <summary>
  225.        ''' Contains information about a simulated mouse event.
  226.        ''' For more info see here:
  227.        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms646273%28v=vs.85%29.aspx
  228.        ''' </summary>
  229.        <Description("Structure used for 'mi' parameter of 'INPUT' structure")>
  230.        Friend Structure MOUSEINPUT
  231.  
  232.            ''' <summary>
  233.            '''
  234.            ''' </summary>
  235.            Public dx As Integer
  236.  
  237.            ''' <summary>
  238.            '''
  239.            ''' </summary>
  240.            Public dy As Integer
  241.  
  242.            ''' <summary>
  243.            '''
  244.            ''' </summary>
  245.            Public mouseData As Integer
  246.  
  247.            ''' <summary>
  248.            '''
  249.            ''' </summary>
  250.            Public dwFlags As Integer
  251.  
  252.            ''' <summary>
  253.            '''
  254.            ''' </summary>
  255.            Public time As Integer
  256.  
  257.            ''' <summary>
  258.            '''
  259.            ''' </summary>
  260.            Public dwExtraInfo As IntPtr
  261.  
  262.        End Structure
  263.  
  264.        ''' <summary>
  265.        ''' Contains information about a simulated keyboard event.
  266.        ''' For more info see here:
  267.        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms646271%28v=vs.85%29.aspx
  268.        ''' </summary>
  269.        <Description("Structure used for 'ki' parameter of 'INPUT' structure")>
  270.        Friend Structure KEYBDINPUT
  271.  
  272.            ''' <summary>
  273.            ''' A virtual-key code.
  274.            ''' The code must be a value in the range '1' to '254'.
  275.            ''' If the 'dwFlags' member specifies 'KEYEVENTF_UNICODE', wVk must be '0'.
  276.            ''' </summary>
  277.            Public wVk As Short
  278.  
  279.            ''' <summary>
  280.            ''' A hardware scan code for the key.
  281.            ''' If 'dwFlags' specifies 'KEYEVENTF_UNICODE',
  282.            ''' 'wScan' specifies a Unicode character which is to be sent to the foreground application.
  283.            ''' </summary>
  284.            Public wScan As Short
  285.  
  286.            ''' <summary>
  287.            ''' Specifies various aspects of a keystroke.
  288.            ''' </summary>
  289.            Public dwFlags As KeyboardInput_Flags
  290.  
  291.            ''' <summary>
  292.            ''' The time stamp for the event, in milliseconds.
  293.            ''' If this parameter is '0', the system will provide its own time stamp.
  294.            ''' </summary>
  295.            Public time As Integer
  296.  
  297.            ''' <summary>
  298.            ''' An additional value associated with the keystroke.
  299.            ''' Use the 'GetMessageExtraInfo' function to obtain this information.
  300.            ''' </summary>
  301.            Public dwExtraInfo As IntPtr
  302.  
  303.        End Structure
  304.  
  305.        ''' <summary>
  306.        ''' Contains information about a simulated message generated by an input device other than a keyboard or mouse.
  307.        ''' For more info see here:
  308.        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/ms646269%28v=vs.85%29.aspx
  309.        ''' </summary>
  310.        <Description("Structure used for 'hi' parameter of 'INPUT' structure")>
  311.        Friend Structure HARDWAREINPUT
  312.  
  313.            ''' <summary>
  314.            ''' The message generated by the input hardware.
  315.            ''' </summary>
  316.            Public uMsg As Integer
  317.  
  318.            ''' <summary>
  319.            ''' The low-order word of the lParam parameter for uMsg.
  320.            ''' </summary>
  321.            Public wParamL As Short
  322.  
  323.            ''' <summary>
  324.            ''' The high-order word of the lParam parameter for uMsg.
  325.            ''' </summary>
  326.            Public wParamH As Short
  327.  
  328.        End Structure
  329.  
  330. #End Region
  331.  
  332.    End Class
  333.  
  334. #End Region
  335.  
  336. #Region " Public Methods "
  337.  
  338.    ''' <summary>
  339.    ''' Sends a keystroke.
  340.    ''' </summary>
  341.    ''' <param name="key">
  342.    ''' Indicates the keystroke to simulate.
  343.    ''' </param>
  344.    ''' <param name="BlockInput">
  345.    ''' If set to <c>true</c>, the keyboard and mouse are blocked until the keystroke is sent.
  346.    ''' </param>
  347.    ''' <returns>
  348.    ''' The function returns the number of events that it successfully
  349.    ''' inserted into the keyboard or mouse input stream.
  350.    ''' If the function returns zero, the input was already blocked by another thread.
  351.    ''' </returns>
  352.    Public Shared Function SendKey(ByVal key As Char,
  353.                                   Optional BlockInput As Boolean = False) As Integer
  354.  
  355.        ' Block Keyboard and mouse.
  356.        If BlockInput Then NativeMethods.BlockInput(True)
  357.  
  358.        ' The inputs structures to send.
  359.        Dim Inputs As New List(Of NativeMethods.INPUT)
  360.  
  361.        ' The current input to add into the Inputs list.
  362.        Dim CurrentInput As New NativeMethods.INPUT
  363.  
  364.        ' Determines whether a character is an alphabetic letter.
  365.        Dim IsAlphabetic As Boolean = Not (key.ToString.ToUpper = key.ToString.ToLower)
  366.  
  367.        ' Determines whether a character is an uppercase alphabetic letter.
  368.        Dim IsUpperCase As Boolean =
  369.            (key.ToString = key.ToString.ToUpper) AndAlso Not (key.ToString.ToUpper = key.ToString.ToLower)
  370.  
  371.        ' Determines whether the CapsLock key is pressed down.
  372.        Dim CapsLockON As Boolean = My.Computer.Keyboard.CapsLock
  373.  
  374.        ' Set the passed key to upper-case.
  375.        If IsAlphabetic AndAlso Not IsUpperCase Then
  376.            key = Convert.ToChar(key.ToString.ToUpper)
  377.        End If
  378.  
  379.        ' If character is UpperCase and CapsLock is pressed down,
  380.        ' OrElse character is not UpperCase and CapsLock is not pressed down.
  381.        If (IsAlphabetic AndAlso IsUpperCase AndAlso CapsLockON) _
  382.        OrElse (IsAlphabetic AndAlso Not IsUpperCase AndAlso Not CapsLockON) _
  383.        OrElse (Not IsAlphabetic) Then
  384.  
  385.            ' Hold the character key.
  386.            With CurrentInput
  387.                .type = NativeMethods.InputType.Keyboard
  388.                .ki.wVk = Convert.ToInt16(CChar(key))
  389.                .ki.dwFlags = 0
  390.            End With : Inputs.Add(CurrentInput)
  391.  
  392.            ' Release the character key.
  393.            With CurrentInput
  394.                .type = NativeMethods.InputType.Keyboard
  395.                .ki.wVk = Convert.ToInt16(CChar(key))
  396.                .ki.dwFlags = NativeMethods.KeyboardInput_Flags.KeyUp
  397.            End With : Inputs.Add(CurrentInput)
  398.  
  399.            ' If character is UpperCase and CapsLock is not pressed down,
  400.            ' OrElse character is not UpperCase and CapsLock is pressed down.
  401.        ElseIf (IsAlphabetic AndAlso IsUpperCase AndAlso Not CapsLockON) _
  402.        OrElse (IsAlphabetic AndAlso Not IsUpperCase AndAlso CapsLockON) Then
  403.  
  404.            ' Hold the Shift key.
  405.            With CurrentInput
  406.                .type = NativeMethods.InputType.Keyboard
  407.                .ki.wVk = NativeMethods.VirtualKeys.SHIFT
  408.                .ki.dwFlags = NativeMethods.KeyboardInput_Flags.KeyDown
  409.            End With : Inputs.Add(CurrentInput)
  410.  
  411.            ' Hold the character key.
  412.            With CurrentInput
  413.                .type = NativeMethods.InputType.Keyboard
  414.                .ki.wVk = Convert.ToInt16(CChar(key))
  415.                .ki.dwFlags = NativeMethods.KeyboardInput_Flags.KeyDown
  416.            End With : Inputs.Add(CurrentInput)
  417.  
  418.            ' Release the character key.
  419.            With CurrentInput
  420.                .type = NativeMethods.InputType.Keyboard
  421.                .ki.wVk = Convert.ToInt16(CChar(key))
  422.                .ki.dwFlags = NativeMethods.KeyboardInput_Flags.KeyUp
  423.            End With : Inputs.Add(CurrentInput)
  424.  
  425.            ' Release the Shift key.
  426.            With CurrentInput
  427.                .type = NativeMethods.InputType.Keyboard
  428.                .ki.wVk = NativeMethods.VirtualKeys.SHIFT
  429.                .ki.dwFlags = NativeMethods.KeyboardInput_Flags.KeyUp
  430.            End With : Inputs.Add(CurrentInput)
  431.  
  432.        End If ' UpperCase And My.Computer.Keyboard.CapsLock is...
  433.  
  434.        ' Send the input key.
  435.        Return NativeMethods.SendInput(Inputs.Count, Inputs.ToArray,
  436.                                       Marshal.SizeOf(GetType(NativeMethods.INPUT)))
  437.  
  438.        ' Unblock Keyboard and mouse.
  439.        If BlockInput Then NativeMethods.BlockInput(False)
  440.  
  441.    End Function
  442.  
  443.    ''' <summary>
  444.    ''' Sends a keystroke.
  445.    ''' </summary>
  446.    ''' <param name="key">
  447.    ''' Indicates the keystroke to simulate.
  448.    ''' </param>
  449.    ''' <param name="BlockInput">
  450.    ''' If set to <c>true</c>, the keyboard and mouse are blocked until the keystroke is sent.
  451.    ''' </param>
  452.    ''' <returns>
  453.    ''' The function returns the number of events that it successfully
  454.    ''' inserted into the keyboard or mouse input stream.
  455.    ''' If the function returns zero, the input was already blocked by another thread.
  456.    ''' </returns>
  457.    Public Shared Function SendKey(ByVal key As Keys,
  458.                                   Optional BlockInput As Boolean = False) As Integer
  459.  
  460.        Return SendKey(Convert.ToChar(key), BlockInput)
  461.  
  462.    End Function
  463.  
  464.    ''' <summary>
  465.    ''' Sends a string.
  466.    ''' </summary>
  467.    ''' <param name="String">
  468.    ''' Indicates the string to send.
  469.    ''' </param>
  470.    ''' <param name="BlockInput">
  471.    ''' If set to <c>true</c>, the keyboard and mouse are blocked until the keystroke is sent.
  472.    ''' </param>
  473.    ''' <returns>
  474.    ''' The function returns the number of events that it successfully
  475.    ''' inserted into the keyboard or mouse input stream.
  476.    ''' If the function returns zero, the input was already blocked by another thread.
  477.    ''' </returns>
  478.    Public Shared Function SendKeys(ByVal [String] As String,
  479.                                    Optional BlockInput As Boolean = False) As Integer
  480.  
  481.        Dim SuccessCount As Integer = 0
  482.  
  483.        ' Block Keyboard and mouse.
  484.        If BlockInput Then NativeMethods.BlockInput(True)
  485.  
  486.        For Each c As Char In [String]
  487.            SuccessCount += SendKey(c, BlockInput:=False)
  488.        Next c
  489.  
  490.        ' Unblock Keyboard and mouse.
  491.        If BlockInput Then NativeMethods.BlockInput(False)
  492.  
  493.        Return SuccessCount
  494.  
  495.    End Function
  496.  
  497. #End Region
  498.  
  499. End Class

Saludos
« Última modificación: 18 Febrero 2014, 08:35 am por Eleкtro » En línea



Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines