I'm interested in displaying Depth data in Unity with Kinect for Windows. Unfortunately, I have Kinect v1.8 and I know this has been easily done with Kinect V2 (Kinect Fusion).
I found this example: https://github.com/rickbarraza/UnityKinectDepthExplorer
I installed all the necessary components and now getting DLLNOTFOUNDEXCEPTION:
Failed to load 'Assets/Plugins/x86_64/KinectUnityAddin.dll'
Concerning all the posts and forums I've been reading so far, It's because I'm using SDK 1.8 (instead of SDK 2.0).
Is there any way how I can use this example with Kinect v1.8? I tried to contact the author as well but he haven't responded back.
Thanks a lot!
I had the same Problem in an University Project maby its not to late for you.
This is an Kinect v1.8 Wrapper i made to read the kinect depth image only. I used the Kinect with MS-SDK from the Unity-Assetstore as an orientation, you dont have to download it. All you need is this Code.
Use The Init() Method to start and the GetDepthArray() Function to get the Deapth Frame.
hope it works for you !
You have to install the Kinect 1.8 sdk or have at least the Kinect10.dll from the 1.8 sdk in your Windows/System32 folder
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
using System;
using System.Runtime.CompilerServices;
public class OwnKinectWrapper : MonoBehaviour {
DepthBuffer db;
#region Nui Variables/Structs/Intefraces
IntPtr streamReferenz;
public struct NuiImageViewArea
{
public int eDigitalZoom;
public int lCenterX;
public int lCenterY;
}
public struct NuiSurfaceDesc
{
uint width;
uint height;
}
public struct DepthBuffer
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 640 * 480, ArraySubType = UnmanagedType.U2)]
public ushort[] pixels;
}
public struct NuiLockedRect
{
public int pitch;
public int size;
public IntPtr pBits;
}
public struct NuiImageFrame
{
public Int64 liTimeStamp;
public uint dwFrameNumber;
public int eImageType;
public int eResolution;
public IntPtr pFrameTexture;
public uint dwFrameFlags_NotUsed;
public NuiImageViewArea ViewArea_NotUsed;
}
[Guid("13ea17f5-ff2e-4670-9ee5-1297a6e880d1")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport()]
public interface INuiFrameTexture
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[PreserveSig]
int BufferLen();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[PreserveSig]
int Pitch();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[PreserveSig]
int LockRect(uint Level, ref NuiLockedRect pLockedRect, IntPtr pRect, uint Flags);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[PreserveSig]
int GetLevelDesc(uint Level, ref NuiSurfaceDesc pDesc);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[PreserveSig]
int UnlockRect(uint Level);
}
#endregion
// Use this for initialization
public int Init() {
int init = 0;
try {
init = NuiInitialize(0x00000020);
Debug.Log("init : " + init);
streamReferenz = IntPtr.Zero;
NuiImageStreamOpen(4, 2, 0, 2, IntPtr.Zero, ref streamReferenz);
}
catch (DllNotFoundException e)
{
string message = "Please check the Kinect SDK installation.";
Debug.LogError(message);
Debug.LogError(e.ToString());
return -1;
}
catch (Exception e)
{
Debug.LogError(e.ToString());
return -1;
}
return init;
}
// Update is called once per frame
void Update()
{
IntPtr imageStreamFrameReferenz = IntPtr.Zero;
int test = NuiImageStreamGetNextFrame(streamReferenz, 0, ref imageStreamFrameReferenz);
if (test == 0) {
NuiImageFrame imageFrame = (NuiImageFrame)Marshal.PtrToStructure(imageStreamFrameReferenz, typeof(NuiImageFrame));
INuiFrameTexture frameTexture = (INuiFrameTexture)Marshal.GetObjectForIUnknown(imageFrame.pFrameTexture);
NuiLockedRect lockedRectPtr = new NuiLockedRect();
IntPtr r = IntPtr.Zero;
frameTexture.LockRect(0, ref lockedRectPtr, r, 0);
db = (DepthBuffer)Marshal.PtrToStructure(lockedRectPtr.pBits, typeof(DepthBuffer));
frameTexture.UnlockRect(0);
NuiImageStreamReleaseFrame(streamReferenz, imageStreamFrameReferenz);
}
}
void OnDisable() {
NuiShutdown();
}
public ushort[] GetDepthArray(){
return db.pixels;
}
[DllImportAttribute(#"Kinect10.dll",EntryPoint="NuiInitialize")]
public static extern int NuiInitialize (uint dwFlags);
[DllImportAttribute(#"Kinect10.dll", EntryPoint = "NuiImageStreamOpen")]
public static extern int NuiImageStreamOpen(int enumImageType,int enumImgageResolution, uint image_Flags, uint frameBufferLimit, IntPtr nextFrameEvent, ref IntPtr streamHandle );
[DllImportAttribute(#"Kinect10.dll", EntryPoint = "NuiImageStreamGetNextFrame")]
public static extern int NuiImageStreamGetNextFrame(IntPtr streamReferenz, uint dwMillisecondsToWait, ref IntPtr ImageFrameReferenz);
[DllImportAttribute(#"Kinect10.dll", EntryPoint = "NuiImageStreamReleaseFrame")]
public static extern int NuiImageStreamReleaseFrame(IntPtr phStreamHandle, IntPtr ppcImageFrame);
[DllImportAttribute(#"Kinect10.dll",EntryPoint="NuiDepthPixelToDepth")]
public static extern ushort NuiDepthPixelToDepth (ushort depthPixel);
[DllImportAttribute(#"Kinect10.dll", EntryPoint = "NuiShutdown")]
public static extern void NuiShutdown();
}
if something is not working or you need help feel free to write some lines
This question is very closely related to How to get the “KeyPress” event from a Word 2010 Addin (developed in C#)? (and in fact includes the sample code from the answer to that question), but this is specifically about developing in Visual Studio (Professional) 2015 for Word 2016 running in Windows 10.
I’m trying to detect when text changes in a Word document from a VSTO add-in. I understand from
How to get the “KeyPress” event from a Word 2010 Addin (developed in C#)? (Nov 14, 2011)
Capturing keydown event of MS Word using C# (Oct 21, 2012)
How to raise an event on MS word Keypress (Oct 24, 2012)
How to trap keypress event in MSword using VSTO? (Nov 5, 2012)
that there’s no event-driven way to do this. Word simply does not send events when text changes.
I’ve seen two workarounds discussed:
Use the WindowSelectionChange event. Unfortunately, this event appears to be sent when the selection is changed by pressing arrow keys, using the mouse, performing undo or redo, and probably other actions, but not when typing or deleting.
Use a low-level keydown event hook. This has been discussed in several of those StackOverflow questions, and was also called a “widely spread technique” in a thread on a Visual Studio forum in February 2014.
I’m trying to use the code in the answer to How to get the “KeyPress” event from a Word 2010 Addin (developed in C#)?, and it seems to observe every keydown event except those sent to Word 2016.
Here’s the code I’m using, for ease of reference.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace KeydownWordAddIn
{
public partial class ThisAddIn
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static IntPtr hookId = IntPtr.Zero;
private delegate IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam);
private static HookProcedure procedure = HookCallback;
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProcedure lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr SetHook(HookProcedure procedure)
{
using (Process process = Process.GetCurrentProcess())
using (ProcessModule module = process.MainModule)
return SetWindowsHookEx(WH_KEYBOARD_LL, procedure, GetModuleHandle(module.ModuleName), 0);
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int pointerCode = Marshal.ReadInt32(lParam);
string pressedKey = ((Keys)pointerCode).ToString();
// Do some sort of processing on key press.
var thread = new Thread(() => {
Debug.WriteLine(pressedKey);
});
thread.Start();
}
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
private void ThisAddIn_Startup(object sender, EventArgs e)
{
hookId = SetHook(procedure);
}
private void ThisAddIn_Shutdown(object sender, EventArgs e)
{
UnhookWindowsHookEx(hookId);
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
When I run Word 2016 with this add-in, I see keydown events sent to the Edge browser and even Visual Studio, but not to Word itself.
Are keydown hooks somehow prevented in Word 2016, or am I doing something wrong?
Everthing should work fine if you don't use a low-level hook in your VSTO add-in.
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetCurrentThreadId();
const int WH_KEYBOARD = 2;
private static IntPtr SetHook(HookProcedure procedure)
{
var threadId = (uint)SafeNativeMethods.GetCurrentThreadId();
return SetWindowsHookEx(WH_KEYBOARD, procedure, IntPtr.Zero, threadId);
}
Please note that you probably also need to create a hook to intercept mouse messages as it is possible to modify the text of a document solely by mouse interactions (e.g. copy and paste via Ribbon or context menu).
VSTO Sample
Here is a complete working VSTO sample including keyboard and mouse hooks:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Office = Microsoft.Office.Core;
namespace SampleAddinWithKeyboardHook
{
public partial class ThisAddIn
{
// NOTE: We need a backing field to prevent the delegate being garbage collected
private SafeNativeMethods.HookProc _mouseProc;
private SafeNativeMethods.HookProc _keyboardProc;
private IntPtr _hookIdMouse;
private IntPtr _hookIdKeyboard;
private void ThisAddIn_Startup(object sender, EventArgs e)
{
_mouseProc = MouseHookCallback;
_keyboardProc = KeyboardHookCallback;
SetWindowsHooks();
}
private void ThisAddIn_Shutdown(object sender, EventArgs e)
{
UnhookWindowsHooks();
}
private void SetWindowsHooks()
{
uint threadId = (uint)SafeNativeMethods.GetCurrentThreadId();
_hookIdMouse =
SafeNativeMethods.SetWindowsHookEx(
(int)SafeNativeMethods.HookType.WH_MOUSE,
_mouseProc,
IntPtr.Zero,
threadId);
_hookIdKeyboard =
SafeNativeMethods.SetWindowsHookEx(
(int)SafeNativeMethods.HookType.WH_KEYBOARD,
_keyboardProc,
IntPtr.Zero,
threadId);
}
private void UnhookWindowsHooks()
{
SafeNativeMethods.UnhookWindowsHookEx(_hookIdKeyboard);
SafeNativeMethods.UnhookWindowsHookEx(_hookIdMouse);
}
private IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
var mouseHookStruct =
(SafeNativeMethods.MouseHookStructEx)
Marshal.PtrToStructure(lParam, typeof(SafeNativeMethods.MouseHookStructEx));
// handle mouse message here
var message = (SafeNativeMethods.WindowMessages)wParam;
Debug.WriteLine(
"{0} event detected at position {1} - {2}",
message,
mouseHookStruct.pt.X,
mouseHookStruct.pt.Y);
}
return SafeNativeMethods.CallNextHookEx(
_hookIdKeyboard,
nCode,
wParam,
lParam);
}
private IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
// handle key message here
Debug.WriteLine("Key event detected.");
}
return SafeNativeMethods.CallNextHookEx(
_hookIdKeyboard,
nCode,
wParam,
lParam);
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support.
/// </summary>
private void InternalStartup()
{
Startup += ThisAddIn_Startup;
Shutdown += ThisAddIn_Shutdown;
}
#endregion
}
internal static class SafeNativeMethods
{
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
public enum HookType
{
WH_KEYBOARD = 2,
WH_MOUSE = 7
}
public enum WindowMessages : uint
{
WM_KEYDOWN = 0x0100,
WM_KEYFIRST = 0x0100,
WM_KEYLAST = 0x0108,
WM_KEYUP = 0x0101,
WM_LBUTTONDBLCLK = 0x0203,
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MBUTTONDBLCLK = 0x0209,
WM_MBUTTONDOWN = 0x0207,
WM_MBUTTONUP = 0x0208,
WM_MOUSEACTIVATE = 0x0021,
WM_MOUSEFIRST = 0x0200,
WM_MOUSEHOVER = 0x02A1,
WM_MOUSELAST = 0x020D,
WM_MOUSELEAVE = 0x02A3,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_MOUSEHWHEEL = 0x020E,
WM_RBUTTONDBLCLK = 0x0206,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_SYSDEADCHAR = 0x0107,
WM_SYSKEYDOWN = 0x0104,
WM_SYSKEYUP = 0x0105
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(
int idHook,
HookProc lpfn,
IntPtr hMod,
uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(
IntPtr hhk,
int nCode,
IntPtr wParam,
IntPtr lParam);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetCurrentThreadId();
[StructLayout(LayoutKind.Sequential)]
public struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
public static implicit operator System.Drawing.Point(Point p)
{
return new System.Drawing.Point(p.X, p.Y);
}
public static implicit operator Point(System.Drawing.Point p)
{
return new Point(p.X, p.Y);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MouseHookStructEx
{
public Point pt;
public IntPtr hwnd;
public uint wHitTestCode;
public IntPtr dwExtraInfo;
public int MouseData;
}
}
}
VBE Add-in Sample
And here is a working sample for the VBA editor (VBE add-in):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Extensibility;
namespace VbeAddin
{
[ComVisible(true)]
[ProgId("VbeAddin.Connect")]
[Guid("95840C70-5A1A-4EDB-B436-40E8BF030469")]
public class Connect : StandardOleMarshalObject, IDTExtensibility2
{
// NOTE: We need a backing field to prevent the delegate being garbage collected
private SafeNativeMethods.HookProc _mouseProc;
private SafeNativeMethods.HookProc _keyboardProc;
private IntPtr _hookIdMouse;
private IntPtr _hookIdKeyboard;
#region IDTExtensibility2 Members
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_mouseProc = MouseHookCallback;
_keyboardProc = KeyboardHookCallback;
SetWindowsHooks();
}
public void OnDisconnection(ext_DisconnectMode removeMode, ref Array custom)
{
UnhookWindowsHooks();
}
public void OnAddInsUpdate(ref Array custom)
{
}
public void OnStartupComplete(ref Array custom)
{
}
public void OnBeginShutdown(ref Array custom)
{
}
#endregion
private void SetWindowsHooks()
{
uint threadId = (uint)SafeNativeMethods.GetCurrentThreadId();
_hookIdMouse =
SafeNativeMethods.SetWindowsHookEx(
(int)SafeNativeMethods.HookType.WH_MOUSE,
_mouseProc,
IntPtr.Zero,
threadId);
_hookIdKeyboard =
SafeNativeMethods.SetWindowsHookEx(
(int)SafeNativeMethods.HookType.WH_KEYBOARD,
_keyboardProc,
IntPtr.Zero,
threadId);
}
private void UnhookWindowsHooks()
{
SafeNativeMethods.UnhookWindowsHookEx(_hookIdKeyboard);
SafeNativeMethods.UnhookWindowsHookEx(_hookIdMouse);
}
private IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
var mouseHookStruct =
(SafeNativeMethods.MouseHookStructEx)
Marshal.PtrToStructure(
lParam,
typeof(SafeNativeMethods.MouseHookStructEx));
// handle mouse message here
var message = (SafeNativeMethods.WindowMessages)wParam;
Debug.WriteLine(
"{0} event detected at position {1} - {2}",
message,
mouseHookStruct.pt.X,
mouseHookStruct.pt.Y);
}
return SafeNativeMethods.CallNextHookEx(
_hookIdKeyboard,
nCode,
wParam,
lParam);
}
private IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
// handle key message here
Debug.WriteLine("Key event detected.");
}
return SafeNativeMethods.CallNextHookEx(
_hookIdKeyboard,
nCode,
wParam,
lParam);
}
}
internal static class SafeNativeMethods
{
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
public enum HookType
{
WH_KEYBOARD = 2,
WH_MOUSE = 7
}
public enum WindowMessages : uint
{
WM_KEYDOWN = 0x0100,
WM_KEYFIRST = 0x0100,
WM_KEYLAST = 0x0108,
WM_KEYUP = 0x0101,
WM_LBUTTONDBLCLK = 0x0203,
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MBUTTONDBLCLK = 0x0209,
WM_MBUTTONDOWN = 0x0207,
WM_MBUTTONUP = 0x0208,
WM_MOUSEACTIVATE = 0x0021,
WM_MOUSEFIRST = 0x0200,
WM_MOUSEHOVER = 0x02A1,
WM_MOUSELAST = 0x020D,
WM_MOUSELEAVE = 0x02A3,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_MOUSEHWHEEL = 0x020E,
WM_RBUTTONDBLCLK = 0x0206,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_SYSDEADCHAR = 0x0107,
WM_SYSKEYDOWN = 0x0104,
WM_SYSKEYUP = 0x0105
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(
int idHook,
HookProc lpfn,
IntPtr hMod,
uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(
IntPtr hhk,
int nCode,
IntPtr wParam,
IntPtr lParam);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetCurrentThreadId();
[StructLayout(LayoutKind.Sequential)]
public struct Point
{
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
public struct MouseHookStructEx
{
public Point pt;
public IntPtr hwnd;
public uint wHitTestCode;
public IntPtr dwExtraInfo;
public int MouseData;
}
}
}
I've experienced this same exact issue in Word 2013 and had to come up with a somewhat "creative" solution. It uses diffplex to monitor changes in the text of the active document and fires events when it changes. It's less than ideal but we do what we have to do to make things work.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Word;
using System.ComponentModel;
namespace WordUtils {
public class TextChangeDetector {
public Word.Application Application;
private BackgroundWorker bg;
public delegate void TextChangeHandler(object sender, TextChangedEventArgs e);
public event TextChangeHandler OnTextChanged;
public TextChangeDetector(Word.Application app) {
this.Application = app;
}
public void Start() {
bg = new BackgroundWorker();
bg.WorkerReportsProgress = true;
bg.WorkerSupportsCancellation = true;
bg.ProgressChanged += bg_ProgressChanged;
bg.DoWork += bg_DoWork;
bg.RunWorkerAsync(this.Application);
}
private void bg_ProgressChanged(object sender, ProgressChangedEventArgs e) {
switch (e.ProgressPercentage) {
case 50: //change
if (OnTextChanged != null) {
OnTextChanged(this, new TextChangedEventArgs((char)e.UserState));
}
break;
}
}
private void bg_DoWork(object sender, DoWorkEventArgs e) {
Word.Application wordApp = e.Argument as Word.Application;
BackgroundWorker bg = sender as BackgroundWorker;
string lastPage = string.Empty;
while (true) {
try {
if (Application.Documents.Count > 0) {
if (Application.ActiveDocument.Words.Count > 0) {
var currentPage = Application.ActiveDocument.Bookmarks["\\Page"].Range.Text;
if (currentPage != null && currentPage != lastPage) {
var differ = new DiffPlex.Differ();
var builder = new DiffPlex.DiffBuilder.InlineDiffBuilder(differ);
var difference = builder.BuildDiffModel(lastPage, currentPage);
var change = from d in difference.Lines where d.Type != DiffPlex.DiffBuilder.Model.ChangeType.Unchanged select d;
if (change.Any()) {
bg.ReportProgress(50, change.Last().Text.Last());
}
lastPage = currentPage;
}
}
}
} catch (Exception) {
}
if (bg.CancellationPending) {
break;
}
System.Threading.Thread.Sleep(100);
}
}
public void Stop() {
if (bg != null && !bg.CancellationPending) {
bg.CancelAsync();
}
}
}
public class TextChangedEventArgs : EventArgs {
public char Letter;
public TextChangedEventArgs(char letter) {
this.Letter = letter;
}
}
}
Usage:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Word;
using WordUtils;
namespace WordAddIn1 {
public partial class ThisAddIn {
TextChangeDetector detector;
private void ThisAddIn_Startup(object sender, System.EventArgs e) {
detector = new TextChangeDetector(Application);
detector.OnTextChanged += detector_OnTextChanged;
detector.Start();
}
void detector_OnTextChanged(object sender, TextChangedEventArgs e) {
Console.WriteLine(e.Letter);
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e) {
detector.Stop();
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup() {
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
How to configure the serial port in kernel module. I am doing this in init module function. same configuration is working in userpsace. I am using the below code to configure the serial port.
mm_segment_t oldfs;
oldfs = get_fs();
set_fs(KERNEL_DS);
fp = filp_open("/dev/ttyS0",O_RDWR | O_NOCTTY | O_NDELAY);
tty = (struct tty_struct *)fp->private_data;
setting the required configuration(tty->termios)
set_fs(oldfs);
Almost all functions of serial port operations are implemented by drivers/tty/serial/serial_core.c. If you want to do it differently then provide your own functions for uart_ops from include/linux/serial_core.h
struct uart_ops {
unsigned int (*tx_empty)(struct uart_port *);
void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
unsigned int (*get_mctrl)(struct uart_port *);
void (*stop_tx)(struct uart_port *);
void (*start_tx)(struct uart_port *);
void (*send_xchar)(struct uart_port *, char ch);
void (*stop_rx)(struct uart_port *);
void (*enable_ms)(struct uart_port *);
void (*break_ctl)(struct uart_port *, int ctl);
int (*startup)(struct uart_port *);
void (*shutdown)(struct uart_port *);
void (*flush_buffer)(struct uart_port *);
void (*set_termios)(struct uart_port *, struct ktermios *new,
struct ktermios *old);
void (*set_ldisc)(struct uart_port *, int new);
void (*pm)(struct uart_port *, unsigned int state,
unsigned int oldstate);
int (*set_wake)(struct uart_port *, unsigned int state);
const char * (*type)(struct uart_port *);
void (*release_port)(struct uart_port *);
int (*request_port)(struct uart_port *);
void (*config_port)(struct uart_port *, int);
int (*verify_port)(struct uart_port *, struct serial_struct *);
int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLL
void (*poll_put_char)(struct uart_port *, unsigned char);
int (*poll_get_char)(struct uart_port *);
#endif
};
In your case, you need to implement set_termios function. Also, look at uart_get_divisor() to know how to set baud rate.