2008-10-14

Simulate key strokes like CAPS LOCK, NUM LOCK, SCROLL LOCK, etc

There are situation when we need to turn on/off or check the status of CAPS LOCK, NUM LOCK and SCROLL LOCK keys. The simplest way to accomplish this is to use SendKeys, but it has it's own disadvantages. So I am using keybd_event API instead. If offers two advantages over SendKeys. First, it doesn't cause the NUM LOCK light to flicker unless you specifically press the NUM LOCK key. Secondly, it's possible to press and hold a key. So it does like this:
Imports System.Runtime.InteropServices

Public Class Form2

Private Declare Sub keybd_event Lib "user32" ( _
ByVal bVk As Byte, _
ByVal bScan As Byte, _
ByVal dwFlags As Integer, _
ByVal dwExtraInfo As Integer _
)

Private Const VK_CAPITAL As Integer = 20
Private Const VK_NUMLOCK As Integer = 144
Private Const VK_SCROLL As Integer = 145
Private Const KEYEVENTF_EXTENDEDKEY As Integer = &H1
Private Const KEYEVENTF_KEYUP As Integer = &H2

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

' Toggle CapsLock

' Simulate the Key Press
keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0)

' Simulate the Key Release
keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)
End Sub

End Class
To toggle NUM LOCK and SCROLL LOCK keys, you just need to replace VK_CAPITAL with appropriate constant variables of NUM LOCK and SCROLL LOCK keys.

Actually speaking, above code can be used to simulate any key. We just need to replace VK_ constants with the appropriate variables of desired keys.

Here I am listing down the virtual keys standard set for your reference.

VK_LBUTTON = 1
VK_RBUTTON = 2
VK_CANCEL = 3
VK_MBUTTON = 4
VK_BACK = 8
VK_TAB = 9
VK_CLEAR = 12
VK_RETURN = 13
VK_SHIFT = &H10
VK_CONTROL = 17
VK_MENU = 18
VK_PAUSE = 19
VK_CAPITAL = 20
VK_ESCAPE = 27
VK_SPACE = &H20
VK_PRIOR = 33
VK_NEXT = 34
VK_END = 35
VK_HOME = 36
VK_LEFT = 37
VK_UP = 38
VK_RIGHT = 39
VK_DOWN = 40
VK_SELECT = 41
VK_PRINT = 42
VK_EXECUTE = 43
VK_SNAPSHOT = 44
VK_INSERT = 45
VK_DELETE = 46
VK_HELP = 47
VK_LWIN = 91
VK_RWIN = 92
VK_APPS = 93
VK_NUMPAD0 = 96
VK_NUMPAD1 = 97
VK_NUMPAD2 = 98
VK_NUMPAD3 = 99
VK_NUMPAD4 = 100
VK_NUMPAD5 = 101
VK_NUMPAD6 = 102
VK_NUMPAD7 = 103
VK_NUMPAD8 = 104
VK_NUMPAD9 = 105
VK_MULTIPLY = 106
VK_ADD = 107
VK_SEPARATOR = 108
VK_SUBTRACT = 109
VK_DECIMAL = 110
VK_DIVIDE = 111
VK_F1 = 112
VK_F2 = 113
VK_F3 = 114
VK_F4 = 115
VK_F5 = 116
VK_F6 = 117
VK_F7 = 118
VK_F8 = 119
VK_F9 = 120
VK_F10 = 121
VK_F11 = 122
VK_F12 = 123
VK_F13 = 124
VK_F14 = 125
VK_F15 = 126
VK_F16 = 127
VK_F17 = 128
VK_F18 = 129
VK_F19 = 130
VK_F20 = 131
VK_F21 = 132
VK_F22 = 133
VK_F23 = 134
VK_F24 = 135
VK_NUMLOCK = 144
VK_SCROLL = 145
VK_LSHIFT = 160
VK_RSHIFT = 161
VK_LCONTROL = 162
VK_RCONTROL = 163
VK_LMENU = 164
VK_RMENU = 165
VK_PROCESSKEY = 229
VK_ATTN = 246
VK_CRSEL = 247
VK_EXSEL = 248
VK_EREOF = 249
VK_PLAY = 250
VK_ZOOM = 251
VK_NONAME = 252
VK_PA1 = 253
VK_OEM_CLEAR = 254

VK_0 thru VK_9 are the same as ASCII '0' thru '9' (&H30 - &H39)
VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (&H41 - &H5A)
2008-10-13

Get drive information of Remote Server using WMI

To use this code you need to add reference to System.Management namespace.

Imports System.Management

Public Class Form1

Dim strFreespace As String
Dim D_Freespace As Double
Dim strTotalspace As String
Dim D_Totalspace As Double

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

CalculateFreeUsed("wabdkp59")
End Sub

Private Sub CalculateFreeUsed(ByVal srvname As String)
Dim msg As String

Try
' Connection credentials to the remote computer -
' not needed if the logged in account has access
Dim oConn As New ConnectionOptions()

oConn.Username = "mum-users\dsakpal"
oConn.Password = "*****"
Dim strNameSpace As String = "\\"

If srvname <> "" Then
strNameSpace += srvname
Else
strNameSpace += "."
End If

strNameSpace += "\root\cimv2"

Dim oMs As New System.Management.ManagementScope(strNameSpace, oConn)

'get Fixed disk stats
Dim oQuery As New System.Management.ObjectQuery("select FreeSpace,Size,Name from Win32_LogicalDisk where DriveType=3")

'Execute the query
Dim oSearcher As New ManagementObjectSearcher(oMs, oQuery)

'Get the results
Dim oReturnCollection As ManagementObjectCollection = oSearcher.[Get]()

'loop through found drives and write out info
For Each oReturn As ManagementObject In oReturnCollection
' Free Space in bytes
D_Freespace = System.Convert.ToDouble(oReturn("FreeSpace"))
' Free Space in GB
strFreespace = (((D_Freespace / 1024) / 1024) / 1024).ToString("0.00")
' Size in bytes
D_Totalspace = System.Convert.ToDouble(oReturn("Size"))
' Size in GB
strTotalspace = (((D_Totalspace / 1024) / 1024) / 1024).ToString("0.00")

msg = "Drive: {0}" & ControlChars.NewLine
msg = msg & "Total space: {1} GB" & ControlChars.NewLine
msg = msg & "Free Space: {2} GB" & ControlChars.NewLine
msg = String.Format(msg, oReturn("Name").ToString(), strTotalspace, strFreespace)
MessageBox.Show(msg)
Next
Catch
msg = "Failed to obtain Server Information."
MessageBox.Show(msg, "Server Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
End Try
End Sub

End Class
2008-10-06

Call DrawItem from another sub

Hi,

In this post I am going to tell you how to call DrawItem from another function, sub or procedure.

What is DrawItem
DrawItem is a event which occurs when a visual aspect of an owner-drawn control changes. The DrawItem event is fired only if the DrawMode property is set to OwnerDrawFixed or OwnerDrawVariable. In this article I am going to use this event to change the the ForeColor of Listbox items.

Simple Example

VB.NET Version:
Public Class Form1

Private Sub Form1_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.Load

ListBox1.DrawMode = DrawMode.OwnerDrawFixed
ListBox1.Items.Add("Red")
ListBox1.Items.Add("Green")
ListBox1.Items.Add("Blue")
End Sub

Private Sub ListBox1_DrawItem( _
ByVal sender As Object, _
ByVal e As System.Windows.Forms.DrawItemEventArgs _
) Handles ListBox1.DrawItem

Dim myFont As Font
If e.Index > -1 Then
e.DrawBackground()
myFont = New Font(ListBox1.Font.Name, ListBox1.Font.Size, ListBox1.Font.Style)
If ListBox1.Items(e.Index).ToString = "Red" Then
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString, myFont, New SolidBrush(Color.Red), e.Bounds)
ElseIf ListBox1.Items(e.Index).ToString = "Green" Then
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString, myFont, New SolidBrush(Color.Green), e.Bounds)
ElseIf ListBox1.Items(e.Index).ToString = "Blue" Then
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString, myFont, New SolidBrush(Color.Blue), e.Bounds)
End If
End If
End Sub

End Class
C# Version:
public class Form1 {

private void Form1_Load(object sender, System.EventArgs e) {
ListBox1.DrawMode = DrawMode.OwnerDrawFixed;
ListBox1.Items.Add("Red");
ListBox1.Items.Add("Green");
ListBox1.Items.Add("Blue");
}

private void ListBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e) {
Font myFont;

if (e.Index > -1) {

e.DrawBackground();
myFont = new Font(ListBox1.Font.Name, ListBox1.Font.Size, ListBox1.Font.Style);

if (ListBox1.Items(e.Index).ToString == "Red") {
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString, myFont, new SolidBrush(Color.Red), e.Bounds);
}
else if (ListBox1.Items(e.Index).ToString == "Green") {
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString, myFont, new SolidBrush(Color.Green), e.Bounds);
}
else if (ListBox1.Items(e.Index).ToString == "Blue") {
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString, myFont, new SolidBrush(Color.Blue), e.Bounds);
}

}
}

}
Example is quite straight forward. In the Load event of the Form I am adding three items to the Listbox control "Red", "Green" and "Blue" respectively. In the DrawItem event I am checking the text of the listbox item being added and doing the coloring stuff.

Real World Scenario
The example given above is very simple. In real world applications the scenarios may not be as simple as this one. I am checking for Red, Green and Blue colors in DrawItem event itself, but what of you want to create a procedure that will add an item to the listbox as well as will specifying the color of that listbox item.

Real World Example
Lets consider a scenario wherein I want to add items to a ListBox control. While adding items to ListBox, I want to specify the ForeColor of the list item. This cannot be done in DrawItem event. Just go through the code snippet given below. I will explain it shortly.

VB.NET Version:
Public Class Form1

Class ListItem
Friend Text As String
Friend ForeColor As Color

Public Sub New(ByVal text As String, ByVal textColor As Color)
Me.Text = text
Me.ForeColor = textColor
End Sub

Public Overrides Function ToString() As String
Return Text
End Function
End Class

Private Sub Form1_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.Load

ListBox1.DrawMode = DrawMode.OwnerDrawFixed
End Sub

Private Sub AddItem(ByVal text As String, ByVal foreColor As Color)
ListBox1.Items.Add(New ListItem(text, foreColor))
End Sub

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

AddItem("One", Color.Red)
AddItem("Two", Color.Green)
AddItem("Three", Color.Blue)
End Sub

Private Sub ListBox1_DrawItem( _
ByVal sender As Object, _
ByVal e As System.Windows.Forms.DrawItemEventArgs _
) Handles ListBox1.DrawItem

Dim myFont As Font
Dim cListItem As ListItem

If e.Index > -1 Then
e.DrawBackground()
myFont = New Font(ListBox1.Font.Name, ListBox1.Font.Size, ListBox1.Font.Style)
cListItem = DirectCast(ListBox1.Items(e.Index), ListItem)
e.Graphics.DrawString(cListItem.ToString, myFont, New SolidBrush(cListItem.ForeColor), e.Bounds)
End If
End Sub

End Class
C# Version:
public class Form1 {

class ListItem {
internal string Text;
internal Color ForeColor;

public ListItem(string text, Color textColor) {
this.Text = text;
this.ForeColor = textColor;
}

public override string ToString() {
return Text;
}
}

private void Form1_Load(object sender, System.EventArgs e) {
ListBox1.DrawMode = DrawMode.OwnerDrawFixed;
}

private void AddItem(string text, Color foreColor) {
ListBox1.Items.Add(new ListItem(text, foreColor));
}

private void Button1_Click(object sender, System.EventArgs e) {
AddItem("One", Color.Red);
AddItem("Two", Color.Green);
AddItem("Three", Color.Blue);
}

private void ListBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e) {
Font myFont;
ListItem cListItem;

if (e.Index > -1) {
e.DrawBackground();
myFont = new Font(ListBox1.Font.Name, ListBox1.Font.Size, ListBox1.Font.Style);
cListItem = (ListItem)ListBox1.Items(e.Index);
e.Graphics.DrawString(cListItem.ToString, myFont, new SolidBrush(cListItem.ForeColor), e.Bounds);
}
}

}

In the above example I have created a custom class called 'ListItem' to represent the item to be added in the Listbox control. This class contains two members which are quite explanatory. They represent Text and ForeColor of list box item. Next, I have created a constructor having two arguments whose values are assigned to the class members. In the next code segment I am overriding the ToString function of the class. ToString function is the default function of any class. When items are added to the listbox, this function gets called. I am using this function to return the text to be displayed in the listbox control.

In the form load event, I am setting the drawMode property of Listbox. DrawMode specifies how the elements of a control are drawn i. e. it gets or sets a value indicating whether user code or the operating system will handle drawing of elements in the list. Its default value is set to 'Normal'. When the DrawMode property is set to Normal, all the elements in a control are drawn by the operating system. As in this example we are going to handle to drawing stuff ourselves in DrawItem event, I set the value of DrawMode to OwnerDrawFixed.

Next, I have created a procedure 'AddItem' which accepts two arguments; text and foreColor. Using this two arguments I am creating a new object of ListItem class and adding it to the Listbox. In the button click event, I am calling the AddItem procedure and passing values to it.

The next code segment is the most important part of this article i.e. DrawItem event. Every time an item is added to the ListBox, DrawItem event is fired.
This event is also fired even when there are no items in the ListBox. So I have added an IF condition to prevent our code from failure. The next statement is e.DrawBackground(). This method basically draws the item selection background. In the next statement I am creating a font object from Listbox control that will be used while drawing the actual string in the ListBox. In the next statement I am getting the object ofListItem class that we added from AddItem method. The next statement is the heart of the DrawItem event which actually draws the ListBox item text.

That's All.