I have an issue with the printing of XPS documents. The first print works correctly but then the print dialog and the prints appears corrupted as you can see in that image.
I tried to use other overloads of the Write function such as the one using a DocumentPaginator as a parameter or the PrintDocument function of the print dialog but it didn't work either.
I noticed that the results depend on the choice of printer. Using the Microsoft XPS Document Writer works correctly but use a real printer or a PDF printer didn't.
Here's the simplest code that reproduces the issue :
public void Execute(object parameter)
{
var printDialog = new PrintDialog();
if (printDialog.ShowDialog() == true)
{
PrintDocument(
"xps_document_filename.xps",
printDialog);
}
}
private static void PrintDocument(string documentPath, PrintDialog printDialog)
{
using (var xpsDocumentSource = new XpsDocument(documentPath, FileAccess.Read))
{
XpsDocumentWriter xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printDialog.PrintQueue);
xpsDocumentWriter.Write(xpsDocumentSource.GetFixedDocumentSequence());
}
}
Related
I have a problem with my application on iOS only (iPad 9.7" 11.3.1), it works perfectly on the simulator and on Android device.
When the app is launched for the first time, the user has to log in. This works fine. After that, the menu form is launched and a Dialog is shown on onShowCompleted():
if (!Preferences.get("download", false)) {
dialog = new Dialog("...");
dialog.setLayout(new BorderLayout());
SpanLabel label = new SpanLabel("...");
dialog.addComponent(BorderLayout.CENTER, label);
dialog.show(Display.getInstance().getDisplayHeight() / 5, ..., ..., ...);
}
In the constructor, a method that downloads informations is launched :
if (!Preferences.get("download", false)) {
dlReferentiel();
}
The method :
public void dlReferentiel() {
source = DataSource.getInstance();
// I also tried with invokeAndBlock() but doesn't work
/*
Display.getInstance().invokeAndBlock(() -> requestS());
Display.getInstance().invokeAndBlock(() -> requestB());
Display.getInstance().invokeAndBlock(() -> requestZ());
Display.getInstance().invokeAndBlock(() -> requestA());
*/
requestS();
requestB();
requestZ();
requestA();
}
The requestX methods get informations from server with ConnectionRequest :
(Exemple with requestA() which needs to be the last because it disposes the dialog, it is the only one that calls the UI)
public void requestA() {
ConnectionRequest connectionRequest = new ConnectionRequest() {
ArrayList<A> as = new ArrayList<>();
#Override
protected void readResponse(InputStream in) throws IOException {
JSONParser json = new JSONParser();
Reader reader = new InputStreamReader(in, "UTF-8");
Map<String, Object> data = json.parseJSON(reader);
for (String s : data.keySet()) {
as.add(new A(s, (String) data.get(s)));
}
}
#Override
protected void postResponse() {
source.createAllA(as); // makes insertions with Transaction
ToastBar.showErrorMessage("Référentiel téléchargé", 10);
dialog.dispose();
Preferences.set("download", true);
}
};
connectionRequest.setUrl(URL_A);
connectionRequest.setPost(true);
NetworkManager.getInstance().addToQueue(connectionRequest);
}
I was able to see some logs with a Mac. Each time, the app crashes after the Dialog is shown and few insertions are made. The same error message is output :
HW kbd: Failed to set (null) as keyboard focus
Unable to get short BSD proc info for 513: No such process
Unable to get proc info for 513: Undefined error: 0
I search for informations about this issue but nothing interesting with Codename One.
I don't know what to do with this error, I tried some things like using invokeAndBlock() or changing build hints like ios.keyboardOpen (just because there is "keyboard" in it) but nothing worked.
Thanks for the help.
I am new to react-native and I seek your help please. What I am planning to do is to get the app icon associated with an app that the user has installed on his device.
I did take a look at this code and realized that I have no way of passing it back to my JS.
Here is what I am doing currently.
private List<String> getNonSystemApps() {
List<PackageInfo> packages = this.reactContext
.getPackageManager()
.getInstalledPackages(0);
List<String> ret = new ArrayList<>();
for (final PackageInfo p: packages) {
if ((p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("name", p.packageName);
jsonObject.put("firstInstallTime", p.firstInstallTime);
jsonObject.put("installLocation", p.installLocation);
jsonObject.put("applicationInfo", p.applicationInfo);
jsonObject.put("permissions", getPermissionsByPackageName(p.packageName));
Drawable icon = reactContext.getPackageManager().getApplicationIcon(p.packageName);
ret.add(jsonObject.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return ret;
}
Can you please help me out with this ?
Thanks
Edit
I managed to get it working, based on Aaron's suggestion, I created another private function just to work with the images. This function will generate the base 64 version of an app's icon.
private String getBitmapOfAnAppAsBase64(String packageName) {
if(packageName.isEmpty() ) return new String("");
String base64Encoded = "";
Bitmap bitmap;
try {
Drawable appIcon = this.reactContext.getPackageManager().getApplicationIcon(packageName);
if(appIcon instanceof BitmapDrawable) {
bitmap= ((BitmapDrawable)appIcon).getBitmap();
} else {
bitmap = Bitmap.createBitmap(appIcon.getIntrinsicWidth(), appIcon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
base64Encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
} catch(Exception e) {
Log.d(TAG,"An error was encounted while getting the package information. The error follows : " + e.toString());
}
return base64Encoded;
}
I then use this generated string in my original function, with the following modifications.
Old Non working code
Drawable icon = reactContext.getPackageManager().getApplicationIcon(p.packageName);
New working code
jsonObject.put("icon", getBitmapOfAnAppAsBase64(p.packageName));
and then in React-Native - its a piece of pie, since it supports base64 already.
"icon" : 'data:image/png;base64,'+installAppObj.icon
Huge thanks to Aaron , for guiding me in the correct direction.
If you haven't already, read through the entire Android Native Modules page. It's not that long and addresses several issues you're likely to run into.
Only these types can be sent to your JS code (via a #ReactMethod):
Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array
So you effectively have two options:
Encode the Drawable to one of these types, then decode it on the JavaScript side, or
Write the file to disk, and send the path over
I'm not sure what type of Drawable the icon is or if there are guarantees. But any of them should be convertible in some way. For example if it's a Bitmap you can do a Bitmap to Base64 String conversion.
I need to be able to convert an Image to a byte Array and then back again. I've followed the google results and it seemed to be working..except it doesn't :)
I am pretty sure it has something to do with the Memory stream (I'm getting that GDI+ error) but I'm using the "using" and I thought I was cleanup up after myself.
private void button1_Click(object sender, EventArgs e)
{
System.Drawing.Image myImage = null;
SetImage(ref myImage); //This one works
SetImage(ref myImage); // This call breaks on
//the first myImage.Save line
}
private void SetImage(ref System.Drawing.Image myImage)
{
try
{
byte[] myImageAsBytes = null;
//First time through we don't have an image already so we load from a file
if (myImage == null)
{
myImage = System.Drawing.Image.FromFile("C:\\temp\\test.jpg");
}
//Convert our Image to a Byte Array.
using (System.IO.MemoryStream myMemoryStream = new System.IO.MemoryStream())
{
myImage.Save(myMemoryStream, myImage.RawFormat);
myImageAsBytes = myMemoryStream.ToArray();
}
//Just debugging
myImage.Dispose();
myImage = null;
GC.Collect();
//And convert it back to an image.
//using (System.IO.MemoryStream myMemoryStream = new System.IO.MemoryStream(myImageAsBytes))
//{
// myImage = System.Drawing.Image.FromStream(myMemoryStream);
//}
System.IO.MemoryStream myMemoryStream2 = new System.IO.MemoryStream(myImageAsBytes);
myImage = System.Drawing.Image.FromStream(myMemoryStream2);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The documentation for Image.FromStream: https://msdn.microsoft.com/en-us/library/93z9ee4x(v=vs.110).aspx
Says:
You must keep the stream open for the lifetime of the Image.
When it comes to MemoryStreams there is actually no point in closing/disposing them. It's the only .NET class I can think of that is IDisposable that doesn't need disposing. It accidentally inherits IDisposable from System.IO.Stream, that's why.
So I would recommend that you just create your memory streams and let them be.
If you were to use Image.FromStream on a physical file, however, maybe you wont like to keep it open. What you could do in that case is to make a copy of the bitmap like this:
Bitmap safeBitmap;
using ( var stream = blah-blah-blah )
using ( var img = Image.FromStream(stream) )
safeBitmap = new Bitmap(img);
I know delphi but not C++. I think you have set myimage to null if myimage is an object, so tried to re-create. Or don't set it to null, just redraw on it or myimage.loadfromstream.
System.Drawing.Image myImage = null;
SetImage(ref myImage); //This one works
myimage :=create;
SetImage(ref myImage);
Its as simple as removing "ref" from everywhere
I suggest you read up what that key word is doing, you will then understand why its breaking it.
rather return the new image from the method.
i.e. change it from void to return the new image.
Update
below is a console version of your code basically unmodified at ALL
and it runs fine.... although i don't agree with the programming at ALL either.
Point is where are you getting an error if it seems to run with no errors
class Program
{
static void Main(string[] args)
{
Dosomething();
}
private static void Dosomething()
{
System.Drawing.Image myImage = null;
SetImage(ref myImage); //This one works
SetImage(ref myImage); // This call breaks on
}
private static void SetImage(ref System.Drawing.Image myImage)
{
try
{
byte[] myImageAsBytes = null;
//First time through we don't have an image already so we load from a file
if (myImage == null)
{
myImage = System.Drawing.Image.FromFile("C:\\temp\\test.jpg");
}
//Convert our Image to a Byte Array.
using (System.IO.MemoryStream myMemoryStream = new System.IO.MemoryStream())
{
myImage.Save(myMemoryStream, myImage.RawFormat);
myImageAsBytes = myMemoryStream.ToArray();
}
//Just debugging
myImage.Dispose();
myImage = null;
GC.Collect();
//And convert it back to an image.
//using (System.IO.MemoryStream myMemoryStream = new System.IO.MemoryStream(myImageAsBytes))
//{
// myImage = System.Drawing.Image.FromStream(myMemoryStream);
//}
System.IO.MemoryStream myMemoryStream2 = new System.IO.MemoryStream(myImageAsBytes);
myImage = System.Drawing.Image.FromStream(myMemoryStream2);
}
catch (Exception ex)
{
}
}
}
I'm trying to attach a PDF File to a Print Dialog, but I haven't find out the way to do it.
I'm using a WPF app, and I have some code related with printing and looks like this:
private void Imprimir()
{
try
{
FixedDocument document = null;
PageContent pageContent = null;
FixedPage fixedPage = null;
PrintDialog printDlg = new PrintDialog();
if (printDlg.ShowDialog() != true)
return;
document.DocumentPaginator.PageSize = new System.Windows.Size(1400, 1450);
fixedPage.Width = document.DocumentPaginator.PageSize.Width;
fixedPage.Height = document.DocumentPaginator.PageSize.Height;
fixedPage.Margin = new Thickness(96, 96, 0, 0);
fixedPage.Children.Add(this);
((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
document.Pages.Add(pageContent);
printDlg.PrintDocument(document.DocumentPaginator, "Impresion Cierre");
fixedPage.Children.Clear();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
}
But, by this way I'm just printing a UI Element added to Fixed Page.
I've looked for other codes, but I find nothing.
So, I don´t know if is possible to add a PDF File stored locally to the Print Dialog ?
Thanks for the help...
Well you cannot do this using PrintDialog. There are several options, depending on your goals:
var printQueue = LocalPrintServer.GetDefaultPrintQueue();
using (var input = File.OpenRead("path_to_your.pdf")) {
using (var job = printQueue.AddJob()) {
using (var output = job.JobStream) {
input.CopyTo(output);
}
}
}
Will silently send print job for your file to local print queue. Print job is configurable.
Alternatively you can use adobe reader to handle that for you (or another pdf reader installed on user's machine) but starting process with path to your pdf as FileName and Verb="print".
One more option is to use third party tools (like ghostscript) which can help you with that.
I have an application with RichTextBox and DocumentViewer (placed in a TabControl), and I want to make something like "hot preview". I've binded DocumentViewer.Document property to RichTextBox.Document
Binding:
<DocumentViewer Document="{Binding Document, Converter={StaticResource FlowDocumentToPaginatorConverter}, ElementName=mainRTB, Mode=OneWay}" />
And this is Converter code:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
FlowDocument d = value as FlowDocument;
DocumentPaginator pagin = ((IDocumentPaginatorSource)d).DocumentPaginator;
FixedDocumentSequence result = null;
Size s = new Size(793.700787402, 1122.519685039);
pagin.PageSize = s;
using (MemoryStream ms = new MemoryStream())
{
TextRange tr = new TextRange(d.ContentStart, d.ContentEnd);
tr.Save(ms, DataFormats.XamlPackage);
Package p = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
Uri uri = new Uri(#"memorystream://doc.xps");
PackageStore.AddPackage(uri, p);
XpsDocument xpsDoc = new XpsDocument(p);
xpsDoc.Uri = uri;
XpsDocument.CreateXpsDocumentWriter(xpsDoc).Write(pagin);
result = xpsDoc.GetFixedDocumentSequence();
}
return result;
}
When I start this application everything is ok until I switch to tab with DocumentViewer. Application crushes and I get such Exception:
Cannot perform a read operation in write-only mode.
What I am doing wrong? Is it possible to make this binding?
The error message is indeed confusing and reason not immediately obvious. Basically you are closing the MemoryStream that holds XpsDocument too early and when the DocumentViewer attempts to read the document it cannot as it is write-only mode (because the stream was closed).
The solution is to not immediately close the MemoryStream until after you have finished viewing the document. To achieve this I wrote an XpsDocumentConverter that returns XpsReference.
Also, as you never been able to convert and display a single XpsDocument you won't have yet encountered the next issue of having multiple packages in the PackageStore with the same Uri. I have taken care of this in my implementation below.
public static XpsDocumentReference CreateXpsDocument(FlowDocument document)
{
// Do not close the memory stream as it still being used, it will be closed
// later when the XpsDocumentReference is Disposed.
MemoryStream ms = new MemoryStream();
// We store the package in the PackageStore
Uri uri = new Uri(String.Format("pack://temp_{0}.xps/", Guid.NewGuid().ToString("N")));
Package pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
PackageStore.AddPackage(uri, pkg);
XpsDocument xpsDocument = new XpsDocument(pkg, CompressionOption.Normal, uri.AbsoluteUri);
// Need to force render the FlowDocument before pagination.
// HACK: This is done by *briefly* showing the document.
DocumentHelper.ForceRenderFlowDocument(document);
XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(xpsDocument), false);
DocumentPaginator paginator = new FixedDocumentPaginator(document, A4PageDefinition.Default);
rsm.SaveAsXaml(paginator);
return new XpsDocumentReference(ms, xpsDocument);
}
public class XpsDocumentReference : IDisposable
{
private MemoryStream MemoryStream;
public XpsDocument XpsDocument { get; private set; }
public FixedDocument FixedDocument { get; private set; }
public XpsDocumentReference(MemoryStream ms, XpsDocument xpsDocument)
{
MemoryStream = ms;
XpsDocument = xpsDocument;
DocumentReference reference = xpsDocument.GetFixedDocumentSequence().References.FirstOrDefault();
if (reference != null)
FixedDocument = reference.GetDocument(false);
}
public void Dispose()
{
Package pkg = PackageStore.GetPackage(XpsDocument.Uri);
if (pkg != null)
{
pkg.Close();
PackageStore.RemovePackage(XpsDocument.Uri);
}
if (MemoryStream != null)
{
MemoryStream.Dispose();
MemoryStream = null;
}
}
}
XpsReference implements IDisposable so remember to call Dispose() on it.
Also, once you resolve the above error the next problem you are likely to encounter will be content not rendering as you would expect. This is caused by the fact you need to clone FlowDocument and it has not undergone a full measure and arrange layout pass. Read
Printing BlockUIContainer to XpsDocument/FixedDocument on how to solve this.