在本文中,将探讨如何开发一款基于Windows Universal Platform (UWP) 的蓝牙打印应用。该应用已在Windows 10 Phone上进行测试,并且运行在Windows 10 Iot Enterprise Edition上。本教程将指导通过创建一个简单的用户界面,连接蓝牙设备,以及发送文件到打印机的整个过程。
应用界面是基于网格布局的,其中包含定义好的列数和行数。所有的行都被设置为自动调整高度。以下是界面布局的HTML代码示例:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
...
</Grid>
网格列中包含了多个堆栈面板(StackPanel),这些面板包含了用户界面元素。根据演示应用的状态,这些堆栈面板会被显示或隐藏。例如,在初始状态下,用户需要选择一个打印机,此时只显示“列出打印机”按钮和空列表。一旦通过点击列表中的打印机名称连接到打印机,包含“列出打印机”和列表的堆栈面板就会折叠(隐藏)起来。
代码基于BTRFCommChat示例。首先,需要更改蓝牙服务描述符,以便在蓝牙发现过程中使用“RfcommServiceId.SerialPort”:
// 查找所有配对的Rfcomm服务实例,并在列表中显示
dataServiceDeviceCollection = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
if (dataServiceDeviceCollection.Count > 0) {
DeviceList.Items.Clear();
foreach (var dataServiceDevice in dataServiceDeviceCollection) {
DeviceList.Items.Add(dataServiceDevice.Name);
}
DeviceList.Visibility = Windows.UI.Xaml.Visibility.Visible;
}
当用户点击一个设备时,应用会尝试创建一个套接字连接:
try {
await dataSocket.ConnectAsync(dataService.ConnectionHostName, dataService.ConnectionServiceName);
dataWriter = new DataWriter(dataSocket.OutputStream);
Panel_SelectPrinter.Visibility = Visibility.Collapsed;
PanelSelectFile.Visibility = Visibility.Visible;
panelDisconnect.Visibility = Visibility.Visible;
DataReader dataReader = new DataReader(dataSocket.InputStream);
ReceiveStringLoop(dataReader);
}
接下来,会显示一个准备好的演示打印文件列表。这个列表是从应用中部署在文件文件夹内的所有文件构建的:
private async void FilesListbox_Loaded(object sender, RoutedEventArgs e) {
try {
FilesListbox.Items.Clear();
var folder = await StorageFolder.GetFolderFromPathAsync(Windows.ApplicationModel.Package.Current.InstalledLocation.Path + @"\files");
IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
foreach (StorageFile f in files) {
FilesListbox.Items.Add(f.Name);
}
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine("ListFiles: " + ex.Message);
}
}
private async void SendFile() {
try {
if (FilesListbox.SelectedIndex == -1) return;
string filename = FilesListbox.SelectedItem.ToString();
var fileToRead = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///files/" + filename, UriKind.Absolute));
byte[] buffer = new byte[1024];
int readcount = 0;
using (BinaryReader fileReader = new BinaryReader(await fileToRead.OpenStreamForReadAsync())) {
int read = fileReader.Read(buffer, 0, buffer.Length);
while (read > 0) {
readcount += read;
Stream streamWrite = dataSocket.OutputStream.AsStreamForWrite();
streamWrite.Write(buffer, 0, read);
streamWrite.Flush();
read = fileReader.Read(buffer, 0, buffer.Length);
}
}
NotifyUser("sendFile " + readcount.ToString(), NotifyType.StatusMessage);
await dataWriter.StoreAsync();
} catch (Exception ex) {
NotifyUser("Error: " + ex.HResult.ToString() + " - " + ex.Message, NotifyType.StatusMessage);
}
}