65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 VBTablet 的 C# 中的数字化仪接口

2009 年 12 月 5 日

CPOL

3分钟阅读

viewsIcon

64590

downloadIcon

2481

在 C# 中使用 VBTablet 的数字化仪设备接口。

引言

本文演示了以下内容

  1. 在 C# 中连接数字化仪平板电脑(Wintab 兼容的数字化仪)。
  2. 处理数字化仪引发的事件并捕获数据。
  3. 在 C# 中使用 VBTablet COM 组件连接数字化仪。

VBTablet 组件用于连接数字化仪设备;该组件可以从以下网址下载:http://www.sourceforge.org/projects/vbtablet/。更多详细信息请访问:http://www.greenreaper.co.uk/,这是开发者的网站。

VBTablet 是用 VB(很可能)编写的 COM 组件。 VB.NET 中的接口可以在“SourceForge”链接上找到,但没有基于 C# 的代码。我现在正在研究数字化仪,因此我尝试了 C# 中的这个接口,并在此处发布。

您应该注意的一件事是,您必须有一个数字化仪平板电脑才能测试此代码。我正在使用 WACOM Intuos4(4X3)。您可以在 http://www.wacom.com/intuos/ 获取有关此硬件的详细信息。

如果您正在开发图形设计器应用程序,这可能是一个起始步骤。本文还演示了在 C# 中使用 COM 组件。

背景

安装设备驱动程序并连接硬件。要理解此代码,您应该对 COM 和委托有一个基本的了解。在这里,我们将数字化仪连接到 PC,并且数字化仪在 C# 代码中被接口化为 VBTablet 对象。您需要添加对包含所有定义的 *VBTablet.dll* 文件的引用。

使用代码

我们必须添加对此命名空间的引用

using VBTablet;

接下来,我们为数字化仪创建一个对象;类 TabletVBTablet 命名空间中定义。

public Tablet Digitizer;

数字化仪在主窗体加载事件中连接。首先,初始化数字化仪。 Tablet 对象(数字化仪)将探测硬件并提供信息。我们在这里获取上下文、压力、最大 X、最大 Y 等。使用此组件,我们甚至可以读取笔尖的 Z 坐标(在 3D 中)。接下来,我们定义用于处理 Tablet 对象(数字化仪)事件的委托。

Digitizer.PacketArrival += new Tablet.PacketArrivalEventHandler(PacketArrival); 

这是处理数据包到达事件的委托。当笔尖接触数字化仪表面时发生。

private void MainFrm_Load(object sender, EventArgs e)
{
    try
    {
        // On Error GoTo errorload
        Digitizer = new Tablet(); //Actually create the tablet object
        sldGranularity.Value = 2; //Set packet granularity value
        //that uses a tablet attribute. Remember not everyone has _your_ tablet.
        Digitizer.UnavailableIsError = false;

        //Tablet.hWnd = frmMain.DefInstance.Handle
        prgX.Maximum = Digitizer.Context.OutputExtentX - Digitizer.Context.OutputOriginX;
        prgY.Maximum = Digitizer.Context.OutputExtentY - Digitizer.Context.OutputOriginY;
        prgZ.Maximum = 255;

        prgPressure.Maximum = (int)Digitizer.Device.NormalPressure.get_Max(true);
        prgTangentPressure.Maximum = (int)Digitizer.Device.TangentPressure.get_Max(true);

        // The Delegates for Digitizer Event Handling
        Digitizer.ContextClosed += 
          new VBTablet.Tablet.ContextClosedEventHandler(ContextClosed);
        Digitizer.ContextOpened += 
          new VBTablet.Tablet.ContextOpenedEventHandler(ContextOpened);
        Digitizer.ContextRepositioned += 
           new Tablet.ContextRepositionedEventHandler(ContextRepositioned);
        Digitizer.ContextUpdated += new Tablet.ContextUpdatedEventHandler(ContextUpdated);
        Digitizer.CursorChange += new Tablet.CursorChangeEventHandler(CursorChange);
        Digitizer.InfoChange += new Tablet.InfoChangeEventHandler(InfoChange);
        Digitizer.ProximityChange += new Tablet.ProximityChangeEventHandler(ProximityChange);
        Digitizer.PacketArrival += new Tablet.PacketArrivalEventHandler(PacketArrival);
    }
    catch (Exception  ex)
    {
        MessageBox.Show(ex.Message + ". Please Connect the Digitizer Device First !!");
    }
}

在使用平板电脑之前,您必须启用它。这是通过先按“连接”按钮,然后再按“启用”按钮来完成的。“连接”按钮会将数字化仪的上下文通过以下方式附加到主窗体的图片框:

IntPtr Hwnd;
Hwnd = this.Handle;

private void cmdConnect_Click(object sender, EventArgs e)
{
    IntPtr Hwnd;
    bool IsDigitizingContext=false;
    string ContextID = "FirstContext";
    Connect.Enabled = false;
    Disconnect.Enabled = true;
    Enable.Enabled = true;
    Disable.Enabled = false;
    chkDigitise.Enabled = true;//Enable Digitize Mode
    Hwnd = this.Handle;
    Digitizer.hWnd = Hwnd;
    Digitizer.AddContext(ContextID, ref IsDigitizingContext);
    Digitizer.SelectContext(ref ContextID);
    Digitizer.Connected = true;
    Digitizer.Context.QueueSize = 32;//Set queue size to a reasonable value

    Deviceinfo();
}

private void Enable_Click(object sender, EventArgs e)
{
    Disable.Enabled = true;
    Enable.Enabled = false;
    InContext();//Call Incontext
    //Check Following Code
   
    Digitizer.Context.TrackingMode = true;
    Digitizer.Context.Enabled = true;
    return;
}

来自数字化仪的数据包具有 X、Y、Z、压力、方位角、高度和光标信息。我们在数据包到达事件中获取此信息。事件处理程序更新主窗体显示;我们还使用一些 GDI 函数在图片框中显示数据。

public void PacketArrival(ref IntPtr ContextHandle, 
         ref int Cursor_Renamed, ref int X , ref int Y , ref int Z, 
         ref int Buttons , ref int Pressure , ref int TangentPressure, 
         ref int Azimuth, ref int Altitude, ref int Twist, ref int Pitch, 
         ref int Roll , ref int Yaw,ref int PacketSerial, ref int PacketTim) 
{
    //Show current stats. Note that it's a good idea not to update
    //if not necessary - 100+ updates a second can really hurt performance
    
    tmpl = System.Math.Abs(X);

    if( tmpl != prgX.Value)
    {
        if( tmpl <= prgX.Maximum )
            prgX.Value = tmpl;
    }

    tmpl = System.Math.Abs(Y);

    if( tmpl != prgY.Value)
    {
        if( tmpl <= prgY.Maximum)
            prgY.Value = tmpl;
    }

    tmpl = System.Math.Abs(Z);
    if( tmpl != prgZ.Value)
    {
        if( tmpl <= prgZ.Maximum)
            prgZ.Value = tmpl;
    }
    tmpl = System.Math.Abs(Pressure);
    if( tmpl != prgPressure.Value)
        prgPressure.Value = tmpl;
    tmpl = System.Math.Abs(TangentPressure);
    if( tmpl != prgTangentPressure.Value)
        prgTangentPressure.Value = tmpl;

    if( Convert.ToInt32(lblX.Text)!= X )
        lblX.Text = X.ToString();
    if( Convert.ToInt32(lblY.Text)!= Y )
        lblY.Text = Y.ToString();
    if( Convert.ToInt32(lblZ.Text)!= Z )
        lblZ.Text = Z.ToString();
    if( Convert.ToInt32(lblCursor.Text)!= Cursor_Renamed )
        lblCursor.Text = Cursor_Renamed.ToString();
    if( Convert.ToInt32(lblPressure.Text)!= Pressure )
        lblPressure.Text = Pressure.ToString();
    if( Convert.ToInt32(lblTangentPressure.Text)!= TangentPressure )
        lblTangentPressure.Text = TangentPressure.ToString();
    if( Convert.ToInt32(lblAzimuth.Text)!= Azimuth )
        lblAzimuth.Text = Azimuth.ToString();
    if( Convert.ToInt32(lblAltitude.Text)!= Altitude )
        lblAltitude.Text = Altitude.ToString();
    if( Convert.ToInt32(lblTwist.Text)!= Twist )
        lblTwist.Text = Twist.ToString();
    if( Convert.ToInt32(lblPitch.Text)!= Pitch )
        lblPitch.Text = Twist.ToString();
    if( Convert.ToInt32(lblRoll.Text)!= Roll )
        lblRoll.Text = Roll.ToString();
    if( Convert.ToInt32(lblYaw.Text)!= Yaw )
        lblYaw.Text = Yaw.ToString();
            
    Pen ppen=new Pen (Color.Red,1);
    Graphics Gr;
    if (Pressure > 0) // 'catch normalpressure and button 1
    {
        if (Digitizer.Context.CursorIsInverted)
        {
            ppen.Color= Color.Red;
            picDraw.Refresh();
        }
        else
        {
            ppen.Color = Color.Blue;
        }
        tmpl = (int)Digitizer.Device.NormalPressure.get_Max(true);
        RectWidth = (int)((Pressure / (float)tmpl) * 100);
        if ((RectWidth >= 0) & (RectWidth <= 20))
            ppen.Color = Color.LawnGreen;
        else if ((RectWidth >= 21) & (RectWidth <= 40))
            ppen.Color = Color.Blue;
        else if((RectWidth >= 41) & (RectWidth <= 100))
            ppen.Color = Color.Red;
        
        try
        {
            Gr = picDraw.CreateGraphics();
            Gr.DrawLine(ppen, X, picDraw.Height - Y, 
                        Xold,picDraw.Height - Yold + 1);
            // Gr.DrawEllipse(ppen, X, picDraw.Height - Y, 1, 1);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message.ToString(), "Error", 
                   MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }
    }
    //   Application.DoEvents(); // Poor Data Capture & Rendering
    Xold=X;
    Yold=Y;
};

设备详细信息由以下函数给出

private void Deviceinfo()
{
    lblDeviceMaxPktRate.Text = "Maximal Update Packet Rate (Packets/sec): " + 
                               Digitizer.Device.MaxPktRate.ToString();
    lblDeviceMargins.Text = "Device Context Margins (x, y, z): " + 
        Digitizer.Device.Margins.X.ToString() + ", " + 
        Digitizer.Device.Margins.Y.ToString() + ", " + 
        Digitizer.Device.Margins.Z.ToString(); ;
    lblDeviceNormalPressure.Text = "Normal Pressure (Min, Max, Resolution, Units): " + 
        Digitizer.Device.NormalPressure.get_Min(true).ToString() + 
        ", " + Digitizer.Device.NormalPressure.get_Max(true).ToString() + 
        " , " + Digitizer.Device.NormalPressure.Resolution.ToString() + 
        " , " + Digitizer.Device.NormalPressure.Units;
    lblDevicePnPID.Text = "Plug-and-Play device ID: " + 
        Digitizer.Device.PnPID.ToString();
    lblDeviceX.Text = "X capabilities (Min, Max, Resolution, Units): " + 
        Digitizer.Device.X.get_Min(true).ToString()+ ", " + 
        Digitizer.Device.X.get_Max(true).ToString() +" ," + 
        Digitizer.Device.X.Resolution.ToString() + " ," + Digitizer.Device.X.Units;
    lblDeviceY.Text = "Y capabilities (Min, Max, Resolution, Units): " + 
        Digitizer.Device.Y.get_Min(true).ToString() + ", " + 
        Digitizer.Device.Y.get_Max(true).ToString() + " ," + 
        Digitizer.Device.Y.Resolution.ToString() + " ," + 
        Digitizer.Device.Y.Units;
    lblDeviceZ.Text = "Z capabilities (Min, Max, Resolution, Units): " + 
        Digitizer.Device.Z.get_Min(true).ToString() + ", " + 
        Digitizer.Device.Z.get_Max(true).ToString() + " ," + 
        Digitizer.Device.Z.Resolution.ToString() + " ," + 
        Digitizer.Device.Z.Units;
    lblDeviceAzimuth.Text = "Azimuth capabilities (Min, Max, Resolution, Units): " + 
        Digitizer.Device.Azimuth.get_Min(true).ToString() + ", " + 
        Digitizer.Device.Azimuth.get_Max(true).ToString() + " ," + 
        Digitizer.Device.Azimuth.Resolution.ToString() + " ," + 
        Digitizer.Device.Azimuth.Units;
    lblDevName.Text = " Device Name : " + Digitizer.Device.GetType().ToString();
    
    lblStatusContexts.Text = "Number of Contexts open : " + 
                             Digitizer.Status.OpenContexts.ToString();
    lblStatusSysContexts.Text = "Number of System Contexts open : " + 
                                Digitizer.Status.OpenSysContexts.ToString();
    lblStatusMaxRate.Text = "Maximum Packet Rate in use (packets/sec): " + 
                            Digitizer.Status.MaxCurrentPktRate.ToString();
    lblStatusMgrHandles.Text = "Number of Manager Handles open : " + 
                               Digitizer.Status.OpenMgrHandles.ToString();
    lblExtensionTag.Text = "Extension ID: " + Digitizer.Extension.ID.ToString();
    lblExtensionAbsSize.Text = "Size of Extension in a Packet (Absolute Mode): " + 
                               Digitizer.Extension.AbsoluteSize.ToString();
    lblExtensionRelSize.Text = "Size of Extension in a Packet (Relative Mode): " + 
                               Digitizer.Extension.RelativeSize.ToString();
    lblExtensionMask.Text = "Extension Or-Mask: " + 
                            Digitizer.Extension.OrMask.MaskValue.ToString();
}

关注点

VBTablet 演示是在 VB.NET 中,没有 C# 版本可用。此代码演示了 VBTablet 实现的 C# 版本。这可以与任何 Wintab 兼容的数字化仪一起使用。我已在 Wacom Intuos4 上成功测试了它。

谢谢

感谢 VBTablet 的开发者 'L Laurence "GreenReaper" Parry'。

© . All rights reserved.