借助Windows 10的普及,微软开始推Universal应用开发。Universal应用其实和Android和iOS应用一样,运行在sandbox中,在桌面环境里exe不能双击运行。打成一个appx包之后可以提交到Windows Store。任何运行Windows 10的设备都可以运行。那么在开发的时候,现有的C/C++ SDK是否可以兼容呢?答案是可以的,不过会有一些限制。如果你想让SDK兼容所有的设备,需要提供行x86, x64, arm三个版本DLL。我用Dynamsoft Barcode SDK做了试验。
参考原文:How to Create a Universal Barcode Reader on Windows 10 with C/C++ Legacy Code
作者:Xiao Ling
翻译:yushulx
准备工作
在Windows 10中激活开发者模式。
Hello World
编写Hello World很简单,可以学习微软的在线教程https://msdn.microsoft.com/en-us/library/windows/apps/dn996906.aspx。
在Universal App中集成C/C++ SDK
创建一个Universal应用。
在 MainPage.xaml中添加Image, Button和TextBlock:
<ScrollViewer Grid.Row="1" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto" VerticalAlignment="Top">
<StackPanel>
<Grid x:Name="Image" Margin="0,0,0,5" VerticalAlignment="Top">
<Image x:Name="PreviewImage" HorizontalAlignment="Left" VerticalAlignment="Top" MaxWidth="600"/>
</Grid>
<StackPanel Orientation="Horizontal" Margin="0, 0, 0, 5" VerticalAlignment="Top">
<Button x:Name="button" Margin="0, 0, 5, 0" Click="button_Click" VerticalAlignment="Top">
<Viewbox MaxHeight="40" MaxWidth="40">
<SymbolIcon Symbol="OpenFile"/>
</Viewbox>
</Button>
<TextBlock x:Name="BarcodeResults" Margin="0,0,0,10" TextWrapping="Wrap" Text="Results:" Height="600" Width="300" VerticalAlignment="Stretch" HorizontalAlignment="Left" />
</StackPanel>
</StackPanel>
</ScrollViewer>
使用FileOpenPicker来加载文件:
FileOpenPicker^ picker = ref new FileOpenPicker();
picker->FileTypeFilter->Append(".bmp");
picker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
从WriteableBitmap中获取图像数据的C++指针:
byte* GetPointerToPixelData(IBuffer^ pixelBuffer, unsigned int *length)
{
if (length != nullptr)
{
*length = pixelBuffer->Length;
}
// Query the IBufferByteAccess interface.
ComPtr<IBufferByteAccess> bufferByteAccess;
reinterpret_cast<IInspectable*>(pixelBuffer)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess));
// Retrieve the buffer data.
byte* pixels = nullptr;
bufferByteAccess->Buffer(&pixels);
return pixels;
}
使用DecodeBuffer检测图像数据。因为没有对应的接口,需要自己构造数据 (BITMAPINFOHEADER + Image data)。BITMAPINFOHEADER为40个字节,再加上实际的数据:
char *total = (char *)malloc(len + 40);
BITMAPINFOHEADER bitmap_info = { 40, width, height, 0, 32, 0, len, 0, 0, 0, 0 };
memcpy(total, &bitmap_info, 40);
char *data = total + 40;
memcpy(data, buffer, len);
获取barcode结果:
iRet = reader.DecodeBuffer((unsigned char*)total, len + 40);
// Output barcode result
pszTemp = (char*)malloc(4096);
if (iRet != DBR_OK)
{
sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));
free(pszTemp);
return nullptr;
}
pBarcodeResultArray paryResult = NULL;
reader.GetBarcodes(&paryResult);
接下来就是要想办法把C String转换成Platform::String^。StackOverflow上可以找到解答:
results = ref new Array<String^>(paryResult->iBarcodeCount);
for (iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)
{
sprintf(pszTemp, "Barcode %d:\r\n", iIndex + 1);
sprintf(pszTemp, "%s Page: %d\r\n", pszTemp, paryResult->ppBarcodes[iIndex]->iPageNum);
sprintf(pszTemp, "%s Type: %s\r\n", pszTemp, GetFormatStr(paryResult->ppBarcodes[iIndex]->llFormat));
pszTemp1 = (char*)malloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
memset(pszTemp1, 0, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
memcpy(pszTemp1, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);
sprintf(pszTemp, "%s Value: %s\r\n", pszTemp, pszTemp1);
// http://stackoverflow.com/questions/11545951/how-to-convert-from-char-to-platformstring-c-cli
std::string s_str = std::string(pszTemp);
std::wstring wid_str = std::wstring(s_str.begin(), s_str.end());
const wchar_t* w_char = wid_str.c_str();
OutputDebugString(w_char);
barcode_result = ref new String(w_char);
results->set(iIndex, barcode_result);
free(pszTemp1);
}
从<Dynamsoft Barcode SDK>\Redist\C_C++目录拷贝DynamsoftBarcodeReaderx86.dll到DynamsoftBarcodeReader\Debug\DynamsoftBarcodeReader\AppX目录。
现在可以通过CTRL+F5或者菜单来运行程序了。
Universal Barcode Reader 截图:
已知问题
开发Universal应用的时候,有些C的接口是受到限制的,因此SDK中提供的DecodeFile接口用不了,因为需要调用fopen。具体限制可以参考CRT functions not supported in Universal Windows Platform apps。
SDK中提供的QR二维码解码失效。
用DecodeBuffer的时候只能使用BMP图像。
源码
https://github.com/dynamsoftsamples/universal-windows-barcode-reader
来源:oschina
链接:https://my.oschina.net/u/1187419/blog/517142