I have used JNA library and this small API (JnaFileChooser)
https://github.com/steos/jnafilechooser
JnaFileChooser fc = new JnaFileChooser();
fc.addFilter("All Files", "*");
fc.addFilter("Pictures", "jpg", "jpeg", "png", "gif", "bmp");
if (fc.showDialog(parent)) {
File f = fc.getSelectedFile();
// do something with f
}
But how do I use JNA to access this dialg "select folder"
The entire dialogue is controlled on the native side. The package you are are using is already accessing that dialog and that button.
Tracing through the source code of the JnaFileChooser class, this dialogue is part of the WindowsFolderBrowser class. The dialog appears using the SHBrowseForFolder() function combined with SHGetPathFromIDList, and returns the path when the Select Folder button is pressed.
final Pointer pidl = Shell32.SHBrowseForFolder(params);
if (pidl != null)
// MAX_PATH is 260 on Windows XP x32 so 4kB should
// be more than big enough
final Pointer path = new Memory(1024 * 4);
Shell32.SHGetPathFromIDListW(pidl, path);
final String filePath = path.getWideString(0);
final File file = new File(filePath);
Ole32.CoTaskMemFree(pidl);
return file;
}
The params variable passed to this function is of native type BROWSEINFO which controls the dialog box. You can see in the code how a few things have been assigned to it (abbreviated version of code):
final Shell32.BrowseInfo params = new Shell32.BrowseInfo();
params.hwndOwner = Native.getWindowPointer(parent);
params.ulFlags = Shell32.BIF_RETURNONLYFSDIRS | Shell32.BIF_USENEWUI;
params.lpszTitle = title;
If you want to change anything else about the dialog, you need to use a callback. One of the elements in BROWSEINFO is BFFCALLBACK lpfn; where you would define that function, e.g., params.lpfn = the defined callback function.
Documentation for BFFCALLBACK indicates you'll use the option to use SendMessage to change the OK button text with BFFM_SETOKTEXT.
Related
This question is related to this previously answered question Share Image on Android Application from Unity Game
My question is this:
Is there a way to share the image WITHOUT using a file? I'd like to remove the sd card read/write permission on Android. I'm not a Java programmer, so I'm having a heck of a time getting it working. None of my attempts have yielded anything.
"Programmer" answered the previous question with the below code, which works great for me. I basically want to use the variable imageBytes instead of the file. Is this even possible?
void takeScreenShotAndShare()
{
StartCoroutine(takeScreenshotAndSave());
}
private IEnumerator takeScreenshotAndSave()
{
string path = "";
yield return new WaitForEndOfFrame();
Texture2D screenImage = new Texture2D(Screen.width, Screen.height);
//Get Image from screen
screenImage.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
screenImage.Apply();
//Convert to png
byte[] imageBytes = screenImage.EncodeToPNG();
System.IO.Directory.CreateDirectory(Application.persistentDataPath + "/GameOverScreenShot");
path = Application.persistentDataPath + "/GameOverScreenShot" + "/DiedScreenShot.png";
System.IO.File.WriteAllBytes(path, imageBytes);
StartCoroutine(shareScreenshot(path));
}
private IEnumerator shareScreenshot(string destination)
{
string ShareSubject = "Picture Share";
string shareLink = "Test Link" + "\nhttps://stackoverflow.com/questions/36512784/share-image-on-android-application-from-unity-game";
string textToShare = "Text To share";
Debug.Log(destination);
if (!Application.isEditor)
{
AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");
intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_SEND"));
AndroidJavaClass uriClass = new AndroidJavaClass("android.net.Uri");
AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject>("parse", "file://" + destination);
intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_STREAM"), uriObject);
intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), textToShare + shareLink);
intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_SUBJECT"), ShareSubject);
intentObject.Call<AndroidJavaObject>("setType", "image/png");
AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");
currentActivity.Call("startActivity", intentObject);
}
yield return null;
}
Unity3d share image on android
You can directly pass the byte array, no need to convert it to file -> uri -> string
Below are java code, but you can easily translate this to JNI wrapper calls
Bundle bundle = new Bundle();
bundle.putByteArray("byteArr", imageBytes); //put byte array to bundle!!!
Intent intent = new Intent(...);
intent.putExtra(bundle );
To retrieve the image byte array in another activity, use below code:
getIntent().getByteArrayExtra("byteArr");
If you wrap each above function calls into a corresponding JNI function, it would be very tedious. You can on the other hand:
Create an android library project
Add two static java functions, one is saveByteArrayToBundle(...), and the other is getByteArrayFromBundle(...)
Compile the android library into an aar file;
then put the aar file into the Assets/ folder (actually any subfolders will do)
Then call the two static java functions as you have done in the OP
Refer to below tutorials if you need to go through step-by-step:
Step-by-Step guide for developing Android Plugin for Unity3D (I)
Step-by-Step guide for developing Android Plugin for Unity3D (II)
I'm using Jacob to call a VB function that resides in a Macro in an Excel file.
Here is my code : [I pass the file and the vb function name as paramaters to the below java method]
private static void callExcelMacro(File file, String macroName) {
ComThread.InitSTA();
final ActiveXComponent excel = new ActiveXComponent("Excel.Application");
try {
// This will open the excel if the property is set to true
excel.setProperty("Visible", new Variant(false));
final Dispatch workbooks = excel.getProperty("Workbooks").getDispatch();
//String eventSink = null ;
int id = Dispatch.get(workbooks, "Count").getInt();
System.out.println("le nbre" + id);
Dispatch.call(workbooks, "Add");
Dispatch workBook = Dispatch.call(workbooks, "Open", file.getAbsolutePath()).toDispatch();
//new DispatchEvents(sourceOfEvent, eventSink, progId)
//new DispatchEvents(workBook, w , "Excel.Application");
//System.out.println("le résultat"+eventSink);
//d.safeRelease();
Variant V1 = new Variant( file.getName() + macroName);
// Calls the macro
final Variant result = Dispatch.call(excel, "Run", V1);
// Saves and closes
//Dispatch.call(workBook, "Save");
com.jacob.com.Variant f = new com.jacob.com.Variant(true);
// Dispatch.call(workBook, "Close", f);
} catch (Exception e) {
e.printStackTrace();
} finally {
excel.invoke("Quit", new Variant[0]);
ComThread.Release();
}
}
The code runs fine, but my problem is that I don't want to call the instrcution
Dispatch workBook = Dispatch.call(workbooks, "Open", file.getAbsolutePath()).toDispatch();
which displays me what the default macro executes (an Interface with input fields).
Is there a way to "Run" the VB function without "Opening" the Excel file ?
Thanks.
there is no way to execute a VBA function in an Excel workbook without opening the file...
Of course, you can prevent the AUto_open macro running by disabling events on the Excel Application object.
In Excel VBA we do this like so:
Application.enableevents=false
(frequently in conjunction with other settings like ScreenUpdating and DisplayAlerts)
in Java maybe you use:
excel.setProperty("EnableEvents", new Variant(false));
I hope that pointers you in the right direction (lol, boom boom !)
Philip
I'm using rundll32 url.dll,FileProtocolHandler my_file.dotx to open files under Windows.
It works fine with .docx documents, but when I try it with .dotx documents (template documents), it creates a new .docx based on the template.
Just as the normal behavior in the windows explorer : when you double-click on a .dotx template file, it creates a new .docx file based on it. If you want to open the real .dotx file, you have to right-click on it and select "open" instead of "new".
Question is: how to do the same with rundll32? Is there an option in the command to force the opening of the underlying template instead of creating a new document?
Edit: I need a way to do it without C functions, just plain text, in the command line (I'm using Java to do it).
Maybe you can wrap a simple C program around ShellExecute, passing the verb OPEN.
ShellExecute(NULL, TEXT("open"),
TEXT("rundll32.exe"), TEXT("url.dll,FileProtocolHandler pathToGadget"),
NULL, SW_SHOWNORMAL);
I found this example here.
edit:
Since you're doing this in Java - you could try a JNI wrapping of the ShellExceute function like this (from the example I found on The Wannabe Java Rockstar and butchered)
public static boolean execute(String file, String parameters) {
Function shellExecute =
Shell32.getInstance().getFunction(SHELL_EXECUTE.toString());
Int32 ret = new Int32();
shellExecute.invoke(ret, // return value
new Parameter[] {
new Handle(), // hWnd
new Str("open"), // lpOperation
new Str(file), // lpFile
new Str(parameters), // lpParameters
new Str(), // lpDirectory
new Int32(1) // nShowCmd
});
if(ret.getValue() <= 32) {
System.err.println("could not execute ShellExecute: " +
file + ". Return: " + ret.getValue());
}
return (ret.getValue() > 32);
}
public static void main(String[] args) {
ShellExecute.execute("rundll32.exe","url.dll,FileProtocolHandler pathToGadget" );
}
I want to add a help screen to my Codename One App.
As the text is longer as other strings, I would like put it in a separate file and add it to the app-package.
How do I do this? Where do I put the text file, and how can I easily read it in one go into a string?
(I already know how to put the string into a text area inside a form)
In the Codename One Designer go to the data section and add a file.
You can just add the text there and fetch it using myResFile.getData("name");.
You can also store the file within the src directory and get it using Display.getInstance().getResourceAsStream("/filename.txt");
I prefer to have the text file in the filesystem instead of the resource editor, because I can just edit the text with the IDE. The method getResourceAsStream is the first part of the solution. The second part is to load the text in one go. There was no support for this in J2ME, you needed to read, handle buffers etc. yourself. Fortunately there is a utility method in codename one. So my working method now looks like this:
final String HelpTextFile = "/helptext.txt";
...
InputStream in = Display.getInstance().getResourceAsStream(
Form.class, HelpTextFile);
if (in != null){
try {
text = com.codename1.io.Util.readToString(in);
in.close();
} catch (IOException ex) {
System.out.println(ex);
text = "Read Error";
}
}
The following code worked for me.
//Gets a file system storage instance
FileSystemStorage inst = FileSystemStorage.getInstance();
//Gets CN1 home`
final String homePath = inst.getAppHomePath();
final char sep = inst.getFileSystemSeparator();
// Getting input stream of the file
InputStream is = inst.openInputStream(homePath + sep + "MyText.txt");
// CN1 Util class, readInputStream() returns byte array
byte[] b = Util.readInputStream(is);
String myString = new String(b);
I am trying to communicate with Excel from a Java/SWT application. I have been able to open a worksheet, open a file and save it but that's about it.
Can anyone point me to some documentation/examples for this? I especially need to know which commands are available. I did try to record macros to inspect. This was useful but did not give me everything I wanted.
This is a sample of what I have been trying so far:
private static OleAutomation openFile(
OleAutomation automation, String fileName) {
Variant workbooks = automation.getProperty(0x0000023c);// get User
// Defined
// Workbooks
Variant[] arguments = new Variant[1];
arguments[0] = new Variant(fileName);
System.out.println("workbooks::\t" + workbooks);
IDispatch p1 = workbooks.getDispatch();
int[] rgdispid = workbooks.getAutomation().getIDsOfNames(new String[] { "Open" });
int dispIdMember = rgdispid[0];
Variant workbook = workbooks.getAutomation().invoke(dispIdMember, arguments);
System.out.println("Opened the Work Book");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
int id = workbook.getAutomation().getIDsOfNames(new String[] { "ActiveSheet" })[0];
System.out.println(id);
Variant sheet = workbook.getAutomation().getProperty(id);
OleAutomation sheetAutomation = sheet.getAutomation();
return (sheetAutomation);
}
Use VBA help MSOffice. Also you can use Object Browser in Office's VB editor.
Not a documentation, but since you asked about the available commands via automation: have you tried the OLE/COM Object viewer that comes with the Windows 2000 resource kit? Download here.