Hand Cursor for Label vba excel - excel

I'm developing an application with many controls. I want to change the mouse cursor when it passes over a Label. I took a look in the option but there you have a limited choice and not what I want. I tried also to upload a mouse icon but I faced two difficulties: the first one is finding an icon under license cc0 and the second one is that Excel doesn't accept the format that I found. Can you please help? Thanks in advance

You can use the Windows API to change the cursor appearance. I'm assuming this is in an Excel UserForm, so you can use the MouseMove event to know when the mouse is over the label.
Here's the code that you would add in the code behind in a form.
Option Explicit
'Api Declarations
Private Declare Function GetCursorInfo Lib "user32" (ByRef pci As CursorInfo) As Boolean
Private Declare PtrSafe Function LoadCursor Lib "user32" Alias "LoadCursorA" (ByVal hInstance As Long, ByVal lpCursorName As Long) As Long
Private Declare PtrSafe Function SetCursor Lib "user32" (ByVal hCursor As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
'You can use the default cursors in windows
Public Enum CursorTypes
IDC_ARROW = 32512
IDC_IBEAM = 32513
IDC_WAIT = 32514
IDC_CROSS = 32515
IDC_UPARROW = 32516
IDC_SIZE = 32640
IDC_ICON = 32641
IDC_SIZENWSE = 32642
IDC_SIZENESW = 32643
IDC_SIZEWE = 32644
IDC_SIZENS = 32645
IDC_SIZEALL = 32646
IDC_NO = 32648
IDC_HAND = 32649
IDC_APPSTARTING = 32650
End Enum
'Needed for GetCursorInfo
Private Type POINT
X As Long
Y As Long
End Type
'Needed for GetCursorInfo
Private Type CursorInfo
cbSize As Long
flags As Long
hCursor As Long
ptScreenPos As POINT
End Type
'Event that handles knowing when the mouse is over the control
Private Sub Label1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
AddCursor IDC_HAND
End Sub
'To set a cursor
Private Function AddCursor(CursorType As CursorTypes)
If Not IsCursorType(CursorType) Then
SetCursor LoadCursor(0, CursorType)
Sleep 200 ' wait a bit, needed for rendering
End If
End Function
'To determine if the cursor is already set
Private Function IsCursorType(CursorType As CursorTypes) As Boolean
Dim CursorHandle As Long: CursorHandle = LoadCursor(ByVal 0&, CursorType)
Dim Cursor As CursorInfo: Cursor.cbSize = Len(Cursor)
Dim CursorInfo As Boolean: CursorInfo = GetCursorInfo(Cursor)
If Not CursorInfo Then
IsCursorType = False
Exit Function
End If
IsCursorType = (Cursor.hCursor = CursorHandle)
End Function

Related

Userform.show on cursor position

i wish to create code that will open form at any form object by mouse hover. For now i have form.show and unload form on mousemove event.
I can add some variable to each object to recognize their position on window and define top left like on example
Private Sub UserForm_Initialize()
If par_hoverForm = uf_Generator.com_MaxQty.Name Then
Me.Top = Application.Top + uf_Generator.Top + uf_Generator.fr_settings.Top + uf_Generator.com_MaxQty.Top + uf_Generator.com_MaxQty.Height + 30
Me.Left = uf_Generator.Left + uf_Generator.fr_settings.Left + uf_Generator.com_MaxQty.Left + 10
End If
End Sub
but is it possible to form.show at cursor position + some offset? this code getting cursor coordinates but i dont know how to convert it to top/left.
#If VBA7 Then
Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
#Else
Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
#End If
' Create custom variable that holds two integers
Type POINTAPI
Xcoord As Long
Ycoord As Long
End Type
Sub GetCursorPosDemo()
Dim llCoord As POINTAPI
' Get the cursor positions
GetCursorPos llCoord
' Display the cursor position coordinates
MsgBox "X Position: " & llCoord.Xcoord & vbNewLine & "Y Position: " & llCoord.Ycoord
End Sub
any advice are welcome
I will show you one way to do it, which should allow you to customize it to your needs.
First, this is the base code to convert the pixels to point and move an object to the pointer. I've set it to be called with another object, but obviously you can code a specific object in there:
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Public Sub position(this As Object)
Dim lngCurPos As POINTAPI
Dim DocZero As POINTAPI
Dim PointsPerPixelY As Double
Dim PointsPerPixelX As Double
Dim hdc As Long
hdc = GetDC(0)
PointsPerPixelY = 72 / GetDeviceCaps(hdc, 90)
PointsPerPixelX = 72 / GetDeviceCaps(hdc, 88)
ReleaseDC 0, hdc
DocZero.Y = ActiveWindow.PointsToScreenPixelsY(0)
DocZero.X = ActiveWindow.PointsToScreenPixelsX(0)
GetCursorPos lngCurPos
this.Top = (lngCurPos.Y - DocZero.Y) * PointsPerPixelY
this.Left = (lngCurPos.X - DocZero.X) * PointsPerPixelX
End Sub
This worked well for my little test object, but not quite for my form.
For my form, I changed the last two rows to: (Your Mileage May Vary)
this.Top = (lngCurPos.Y - DocZero.Y) * PointsPerPixelY + this.Height * 2.2
this.Left = (lngCurPos.X - DocZero.X) * PointsPerPixelX - this.Width / 2.5
Then, in my Form1 TextBox, I use Call position(UserForm2) in the MouseMove event to update the position of UserForm2 constantly.
One problem I had, was that I was also calling UserForm2.show, which kept resetting the position, making it jump around.
To get around this, I added another function:
Public Function IsLoaded(formName As String) As Boolean
Dim frm As Object
For Each frm In VBA.UserForms
If frm.Name = formName Then
IsLoaded = True
Exit Function
End If
Next frm
IsLoaded = False
End Function
And then my UserForm1 Code looks like this:
Private Sub TextBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If Not IsLoaded("UserForm2") Then UserForm2.show
Call position(UserForm2)
End Sub
I did not add any code to remove Form2 again, since you have that already.
This was my result:

InkPicture renders incorrectly when resized at specific Windows Display Scales

Using Excel/VBA I have made an Excel userform containing only an InkPicture control. I have managed to load a picture (Stretch mode), make the form resizable (API calls), resize the inkpicture upon resize. This is all working perfectly well.
I also need to resize the Ink manually, as it does not scale with the InkPicture. This should also be easily implemented with InkPicture1.Renderer.ScaleTransform and it works perfectly well - most of the time!
Problem: When resizing the userform the ScaleTransform function will stop scaling in either horizontal or vertical direction - but only at specific Windows Display Scales: 125%, 175%, 200% and 225% - whereas scaling 100%, 150% and 250% works perfectly.
The change of behavior at different Windows Display Scales is weird and I have looked for driver updates and performance bottlenecks.
I am uncertain if Display Scale only applies to touchscreens.
The have the same problem on both my computers:
- Microsoft Surface Pro 6 (i5), Windows 10, Office 365 - Excel 32bit
- Lenovo Yoga (i7), Windows 10, Office 365 - Excel 64bit.
Both are touchscreens, using onboard Intel Graphics. Running on external monitors makes no change.
I have investigated:
- Windows, Office and all Drivers should be up to date
- Disabling hardware acceleration (not applicable on my computers)
- Alternative code: using inkpicture.resize event instead
- Alternative code: ScaleTransforming one direction at a time
To reproduce the error you need to...
- Create a macro enabled workbook
- Create UserForm (UserForm1)
- Add the InkPicture ActiveX control to the project
- Insert an InkPicture control (InkPicture1)
- Copy VBA code below into the project
Paste into module and run as macro:
Public Sub OpenUserForm1()
UserForm1.Show
End Sub
Paste into userform1 code:
Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function DrawMenuBar Lib "user32" (ByVal hWnd As LongPtr) As Long
Dim widthBefore As Double
Dim heightBefore As Double
Private Sub UserForm_Initialize()
Me.InkPicture1.Top = 0
Me.InkPicture1.Left = 0
widthBefore = Me.InkPicture1.Width
heightBefore = Me.InkPicture1.Height
Call DrawForm
End Sub
Private Sub UserForm_Activate()
Call MakeFormMaximizable
End Sub
Private Sub UserForm_Resize()
Call DrawForm
End Sub
Private Sub DrawForm()
If Me.InsideHeight = 0 Or Me.InsideWidth = 0 Then Exit Sub
Me.InkPicture1.Width = Me.InsideWidth
Me.InkPicture1.Height = Me.InsideHeight
Dim hMultiplier As Single, vMultiplier As Single
hMultiplier = Me.InkPicture1.Width / widthBefore
vMultiplier = Me.InkPicture1.Height / heightBefore
' This function messes up!
Me.InkPicture1.Renderer.ScaleTransform hMultiplier, vMultiplier
widthBefore = Me.InkPicture1.Width
heightBefore = Me.InkPicture1.Height
End Sub
Private Sub MakeFormMaximizable()
Dim BitMask As LongPtr
Dim Window_Handle As LongPtr
Dim WindowStyle As LongPtr
Dim Ret As LongPtr
Const GWL_STYLE As Long = -16
Const WS_THICKFRAME As Long = &H40000
Const MAX_BOX As Long = &H10000
Box_Type = MAX_BOX
Window_Handle = GetForegroundWindow()
WindowStyle = GetWindowLongPtr(Window_Handle, GWL_STYLE)
BitMask = WindowStyle Or Box_Type Or WS_THICKFRAME
Ret = SetWindowLongPtr(Window_Handle, GWL_STYLE, BitMask)
Ret = DrawMenuBar(Window_Handle)
End Sub
To get Wanted/Expected behavior:
- Set Graphic Display Scale to 100% (followed by logout/login)
- Open Excel workbook / Open Userform
- Draw ink on userform
- Resizing the userform will be completely smooth and seamless - perfect!
To get Weird behavior:
- Set Graphic Display Scale to 200% (followed by logout/login)
- Open Excel workbook / Open Userform
- Draw ink on userform
- When resizing the userform the drawn ink no longer follows. It either only scales in one direction, or scales in a direction that is not being scaled.
I hope someone can reproduce the same error/behavior, has had similar experience, has an idea or ideally a fix.
Thanks a lot.
I found a work around. You need to ignore the calculations the InkPicture Control makes on its Rendering Transform Matrix and instead use the Inkpicture.SetViewTransform and the InkTransform.SetTranform functions manually. The code is quite clear and now it will make your UserForm, InkPicture and your Ink resize coordinated and smoothly across all display settings (those tested anyways).
However, the scale factor will not be consistent across display settings - you need to calibrate the coordinate systems! I have done this by creating an initial scaling factor with the function Inkpicture.GetViewTransform. This needs to be called from Form_Init and I have wrapped the code in function GetInitScale in the code below.
Here is the full modified code except UserForm1.show:
Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function DrawMenuBar Lib "user32" (ByVal hWnd As LongPtr) As Long
Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hdc As Long) As Long
Private Declare PtrSafe Function GetDeviceCaps Lib "Gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long
Const HWND_DESKTOP As Long = 0
Const LOGPIXELSX As Long = 88
Const LOGPIXELSY As Long = 90
Const TWIPSPERINCH = 1440
Dim widthBefore As Double, heightBefore As Double
Dim xInitScale As Double, yInitScale As Double
Private Sub UserForm_Initialize()
widthBefore = Me.InkPicture1.Width
heightBefore = Me.InkPicture1.Height
Me.InkPicture1.Top = 0
Me.InkPicture1.Left = 0
Call GetInitScale
Call DrawForm
End Sub
Private Sub UserForm_Activate()
Call MakeFormMaximizable
End Sub
Private Sub UserForm_Resize()
Call DrawForm
End Sub
Private Sub DrawForm()
Me.InkPicture1.Width = Me.InsideWidth
Me.InkPicture1.Height = Me.InsideHeight
Call ScaleInk
End Sub
Private Sub GetInitScale()
Dim aTransform As New InkTransform
Dim eM11 As Single, eM12 As Single, eM21 As Single, eM22 As Single, eDx As Single, eDy As Single
' Remember initial transform to ensure robustness for diffrent display settings
Me.InkPicture1.Renderer.GetViewTransform aTransform
aTransform.GetTransform eM11, eM12, eM21, eM22, eDx, eDy
xInitScale = eM11
yInitScale = eM22
End Sub
Private Sub ScaleInk()
Dim aTransform As New InkTransform
Dim eM11 As Single, eM22 As Single
' Set transformation matrix manually
eM11 = xInitScale * Me.InkPicture1.Width / widthBefore
eM22 = yInitScale * Me.InkPicture1.Height / heightBefore
' Set new Transform
aTransform.SetTransform eM11, 0, 0, eM22, 0, 0
Me.InkPicture1.Renderer.SetViewTransform aTransform
End Sub
Private Sub MakeFormMaximizable()
Dim BitMask As LongPtr
Dim Window_Handle As LongPtr
Dim WindowStyle As LongPtr
Dim Ret As LongPtr
Const GWL_STYLE As Long = -16
Const WS_THICKFRAME As Long = &H40000
Const MAX_BOX As Long = &H10000
Box_Type = MAX_BOX
Window_Handle = GetForegroundWindow()
WindowStyle = GetWindowLongPtr(Window_Handle, GWL_STYLE)
BitMask = WindowStyle Or Box_Type Or WS_THICKFRAME
Ret = SetWindowLongPtr(Window_Handle, GWL_STYLE, BitMask)
Ret = DrawMenuBar(Window_Handle)
End Sub
Hope this becomes useful to someone. It certainly was to me :-)
/Cheers

Focus to MgsBox when Excel is not active

I have checked related questions such as this or this one but the solutions there do not seem to solve my problem.
I am running a VBA script on my computer. The script takes a few minutes to execute and while waiting I am checking other things in my computer. To get my attention once the script has finished running, I have included a MsgBox at the end of my script. However, because Excel is not active/selected when the script finishes, I cannot see it - only when I reactivate/select Excel.
How can I bring into focus the MsgBox when Excel is not active? I have already tried the following tweaks but they do not work:
ThisWorkbook.Activate:
...
ThisWorkbook.Activate
MsgBox "..."
...
AppActivate() (this command threw an error):
...
AppActivate("Microsoft excel")
MsgBox "..."
...
How about playing a sound when the program finishes?
Place this declaration at the top of a standard code module, above any procedures existing there.
Public Declare Function Beep Lib "kernel32" _
(ByVal dwFreq As Long, _
ByVal dwDuration As Long) As Long
If you place this procedure in the same module you may not need it to be public. Adjust pitch and duration to your preference.
Sub EndSound()
Beep 500, 1000
End Sub
Then place the procedure call at the end of your program.
Call EndSound
I suppose you might use a more elaborate sound - may I suggest a couple of bars from Beethoven's 5th? Modify the EndSound procedure. Chip Pearson has more on this idea.
Try:
Application.WindowState = xlMaximized
Disclaimer: This is not my code and I do not know who the author is. I had this code in my database.
Put your code in Sub Sample(). I have shown where you can insert your code. Once the code is run, Excel will flash 5 times. you can change this number by changing Private Const NumberOfFlashes = 5
Paste this in a Module.
Option Explicit
Private Type FLASHWINFO
cbSize As Long
Hwnd As Long
dwFlags As Long
uCount As Long
dwTimeout As Long
End Type
Private Const FLASHW_STOP As Long = 0
Private Const FLASHW_CAPTION As Long = &H1
Private Const FLASHW_TRAY As Long = &H2
Private Const FLASHW_ALL As Long = (FLASHW_CAPTION Or FLASHW_TRAY)
Private Const FLASHW_TIMER As Long = &H4
Private Const FLASHW_TIMERNOFG As Long = &HC
Private FLASHW_FLAGS As Long
Private Declare Function LoadLibrary Lib "kernel32" _
Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" _
(ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" _
(ByVal hLibModule As Long) As Long
Private Declare Function FlashWindowEx Lib "user32" _
(FWInfo As FLASHWINFO) As Boolean
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Const NumberOfFlashes = 5
Private Function APIFunctionPresent(ByVal FunctionName _
As String, ByVal DllName As String) As Boolean
Dim lHandle As Long
Dim lAddr As Long
lHandle = LoadLibrary(DllName)
If lHandle <> 0 Then
lAddr = GetProcAddress(lHandle, FunctionName)
FreeLibrary lHandle
End If
APIFunctionPresent = (lAddr <> 0)
End Function
Sub Sample()
'
' Put your code here. Once that code finishes, Excel will FLASH
'
Dim udtFWInfo As FLASHWINFO
If Not APIFunctionPresent("FlashWindowEx", "user32") Then Exit Sub
With udtFWInfo
.cbSize = Len(udtFWInfo)
.Hwnd = Application.Hwnd
.dwFlags = FLASHW_FLAGS Or FLASHW_TRAY
.uCount = NumberOfFlashes
.dwTimeout = 0
End With
Call FlashWindowEx(udtFWInfo)
MsgBox "Done"
End Sub
The easiest way is to probably to create a userform instead then set the focus to this when it initialises.
Code in the userform to show as modal:
Private Declare Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName _
As String, ByVal lpWindowName As String) As Long
Private Declare Function SetWindowPos Lib "User32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
Private Const FLAGS As Long = SWP_NOMOVE Or SWP_NOSIZE
Private Const HWND_TOPMOST = -1
Private Sub UserForm_Initialize()
Dim hwnd As Long: hwnd = FindWindow(vbNullString, Me.Caption)
If hwnd > 0 Then SetWindowPos hwnd, HWND_TOPMOST, 0, 0, 0, 0, FLAGS ' Set Modal
End Sub

Make my code wait until cursor is loading MS Excel 2016

I am doing some automation work to do repeated copy paste work. Sometimes the server will be so slow. In that time i would be using the below code to wait until the cursor wait goes to normal
Option Explicit
Private Const IDC_WAIT As Long = 32514
Private Type POINT
x As Long
y As Long
End Type
Private Type CURSORINFO
cbSize As Long
flags As Long
hCursor As Long
ptScreenPos As POINT
End Type
Private Declare Function GetCursorInfo _
Lib "user32" (ByRef pci As CURSORINFO) As Boolean
Private Declare Function LoadCursor _
Lib "user32" Alias "LoadCursorA" _
(ByVal hInstance As Long, ByVal lpCursorName As Long) As Long
Public Function IsWaitCursor() As Boolean
' Get handle to wait cursor
Dim handleWaitCursor As Long
handleWaitCursor = LoadCursor(ByVal 0&, IDC_WAIT)
Dim pci As CURSORINFO
pci.cbSize = Len(pci)
' Retrieve information about the current cursor
Dim ret As Boolean
ret = GetCursorInfo(pci)
If ret = False Then
MsgBox "GetCursorInfo failed", vbCritical
Exit Function
End If
' Returns true when current cursor equals to wait cursor
IsWaitCursor = (pci.hCursor = handleWaitCursor)
End Function
The above code worked fine for me in MS Excel 2013 32-bit. But now I am using MS Excel 64-bit and the above code is not working. Someone please tell me what needs to be done
Private Const IDC_WAIT As Long = 32514
Private Type POINT
X As Long
Y As Long
End Type
Private Type CURSORINFO
cbSize As Long
flags As Long
hCursor As LongPtr
ptScreenPos As POINT
End Type
Private Declare PtrSafe Function GetCursorInfo _
Lib "User32" (ByRef pci As CURSORINFO) As Boolean
Private Declare PtrSafe Function LoadCursor Lib "User32" Alias "LoadCursorA" (ByVal hInstance As Long, ByVal lpCursorName As Long) As LongPtr
Public Function IsWaitCursor() As Boolean
' Get handle to wait cursor
Dim handleWaitCursor As LongPtr
handleWaitCursor = LoadCursor(ByVal 0&, IDC_WAIT)
Dim pci As CURSORINFO
pci.cbSize = Len(pci)
' Retrieve information about the current cursor
Dim ret As Boolean
ret = GetCursorInfo(pci)
If ret = False Then
MsgBox "GetCursorInfo failed", vbCritical
Exit Function
End If
' Returns true when current cursor equals to wait cursor
IsWaitCursor = (pci.hCursor = handleWaitCursor)
End Function
The above code worked for me. I changed the Long datatype to LongPtr

Is there any possible way to track the windows lock and unlock time using vba excel

I want to track the time for windows lock and unlock.
Is there any possible way to track the windows lock and unlock time using vba excel?
Thanks in advance.
Private Declare Function SwitchDesktop Lib "user32" (ByVal hDesktop As Long) As Long
Private Declare Function OpenDesktop Lib "user32" Alias "OpenDesktopA" (ByVal lpszDesktop As String, ByVal dwFlags As Long, ByVal fInherit As Long, ByVal dwDesiredAccess As Long) As Long
Private Declare Function CloseDesktop Lib "user32" (ByVal hDesktop As Long) As Long
Private Const DESKTOP_SWITCHDESKTOP As Long = &H100
Function Check_If_Locked() As String
Dim p_lngHwnd As Long
Dim p_lngRtn As Long
Dim p_lngErr As Long
p_lngHwnd = OpenDesktop(lpszDesktop:="Default", dwFlags:=0, fInherit:=False, dwDesiredAccess:=DESKTOP_SWITCHDESKTOP)
If p_lngHwnd = 0 Then
system = "Error"
Else
p_lngRtn = SwitchDesktop(hDesktop:=p_lngHwnd)
p_lngErr = Err.LastDllError
If p_lngRtn = 0 Then
If p_lngErr = 0 Then
system = "Locked"
Else
system = "Error"
End If
Else
system = "Unlocked"
End If
p_lngHwnd = CloseDesktop(p_lngHwnd)
End If
Check_If_Locked = system
End Function
Private Sub Form_Timer()
Debug.Print Check_If_Locked
End Sub
You are probably better off to look in the event log afterwards rather than trying to use Excel to track in realtime when this happens. See this answer for the event log id values.
There is also this post on SuperUser.

Resources