How can I access the Apple Events "openFile" event in C++? - c++

I'm interested in writing a small utility in C++ for Mac OS X to read, parse, save (over)write a file. I don't need any GUI, menus, or windows.
What type of project template do I need to start with in XCode?
How can I access the file that is passed in? (It's passed with Apple Events openFile, right?)
I've done a little C++ but nothing on Mac. Links appreciated, code samples appreciated more.

How do you intend to pass files to your application?
If it's via the command line then you would use the Command Line Tool template and access the command line parameters just as you would on any POSIX platform (argc and argv).
If you want to pass files to your application using Finder, say, by dropping files onto the application icon, then you would use the Cocoa Application template.
The Info.plist file contains your application configuration and supported document types, similar to the registry on Windows.
You configure Info.plist via the "Info" tab of your Project Settings (It's the top-most file in the file navigator in XCode). Click the "Add" button in the lower right, then select "Add Document Type" to add a document type that your application will accept. To accept all documents, set the document name to All and set the extension to *. More info is here.
Add a LSUIElement key in your Info.plist, and set its value to YES to indicate that your application has no UI. This key is also displayed as "Application is agent" in XCode. More info on LSUIElement is here.
In your MainMenu.xib, you can delete the Window and Font Manager objects that are there by default, since you won't be needing them.
Rename the AppDelegate.m file to AppDelegate.mm, so that it's compiled as Objective-C++. This will allow you to use C++ code in that file.
In the applicationDidFinishLaunching: delegate method, add [NSApp terminate:nil]; so that your app quits immediately when it's done its work.
Add the following method to AppDelegate.mm:
- (BOOL)application:(NSApplication*)app openFile:(NSString *)filename
{
NSLog(#"Opening file %#", filename);
char* cFilename = [filename UTF8String];
// Your C++ code goes here
return YES;
}
That's it. The rest is your C++ code. You can add any C++ code to AppDelegate.mm that you want. E.g.:
#include <string>
#include <iostream>
#include "MyCppFileProcessor.h"
- (BOOL)application:(NSApplication*)app openFile:(NSString *)filename
{
std::string cFilename([filename UTF8String]);
std::cout << "Processing file: " << cFilename << std::endl;
MyCppFileProcessor fileProcessor;
fileProcessor.processFile(cFilename);
return YES;
}
This code will run whenever you drop a document onto your Application's icon in Finder.

1)Use the Command Line Tool template. There are several options for this template. You may select C++ from the menu.
2)As far as I know IOstream will work just fine. Also, there's an argument parameter on your main() function, you may get the file name from these args.
http://www.cplusplus.com/reference/iostream/

Related

wxWidgets include image during compile time

I've been trying to make a simple wxWidgets program with just a button with a picture on it. I've been able to make the button with the image on it easily enough, but my problem arises when including it.
So far, I've only been able to fetch the image during run-time (the image has to be in the same folder as the .exe file; otherwise, I get error 2: the system cannot find the file specified). With this method, I have no problems -- the program works just fine. What I'm trying to do, however, is to #include the file so that it is embedded during compile-time, so that it doesn't need to be available during run-time.
I've tried #including the file (both as .png and as .xpm), and I've also tried adding it to the resource includes (this is on Visual Studio 2017). Neither of these worked -- the first method still required the image to be in the same folder, and the second failed during compilation (as far as I can tell, it wasn't able to read the .xpm file).
Here is the relevant code, if it helps:
/*relevant includes*/
#include "happyFace.png" //this isn't working. the file is still needed
||
#include "happyFace.xpm" //ditto
/*I have also tried putting these lines in the resource includes.*/
/*code*/
wxInitAllImageHandlers();
wxBitmap bitmap("happyFace.xpm", wxBITMAP_TYPE_XPM); //only works in same directory at run-time
||
wxBitmap bitmap("happyFace.png", wxBITMAP_TYPE_PNG); //ditto
wxButton *button = new wxButton(this, ID_BMP_BUTTON);
button->SetBitmap(bitmap);
//the rest of the button programming and stuff
Sorry if I haven't provided enough information; I can provide more if necessary. I would really appreciate any help. Thanks!
Two possibilities... Number 1 is simplest. It's been a long time since I wrote the code I'm looking at, so the details are fuzzy.
In Visual Studio, Solution Explorer, add the image into the resource files. Assume the name of the resourse is sample.rc. Then it can be used like so to set the main icon...
SetIcon(wxICON(sample));
Method 1 must be used in order for MS Windows Explorer to display the main icon. I do not remember how to use .rc resources for other things, but it should be easy to figure out.
I did it this way before I discovered VS resource (.rc) files. Compile the file-image into the program "by hand." In other words, write a program that will read an image file and produce bit-for-bit copy in a .cpp file. Then compile that .cpp into the program. Here I have the file-image in memory as an object named dj::main_cursor. Note that the in-memory version is a bit-for-bit copy of a .cur file.
dj::captured_file &c1file(dj::main_cursor);
wxMemoryInputStream cistr(c1file.contents, c1file.size);
cursor1 = wxCursor(wxImage(cistr, wxBITMAP_TYPE_CUR));
FYI, I defined the structure dj::captured_file like so:
struct captured_file {
const char *name;
const unsigned long size;
const void *contents;
captured_file(const char*fn, size_t sz, const void*c)
: name(fn)
, contents(c)
, size(sz)
{}
};
See also, Embedding PNG Images into Windows RC Files
I found some other documentation.
Resources and Application Icon All applications using wxMSW should
have a Windows resource file (.rc extension) and this file should
include include/wx/msw/wx.rc file which defines resources used by
wxWidgets itself.
Among other things, wx.rc defines some standard icons, all of which
have names starting with the "wx" prefix. This normally ensures that
any icons defined in the application's own resource file come before
them in alphabetical order which is important because Explorer
(Windows shell) selects the first icon in alphabetical order to use as
the application icon which is displayed when viewing its file in the
file manager. So if all the icons defined in your application start
with "x", "y" or "z", they won't be used by Explorer. To avoid this,
ensure that the icon which is meant to be used as the main application
icon has a name preceding "wxICON" in alphabetical order.
http://docs.wxwidgets.org/3.1.0/page_port.html
Here is how you should do it:
#include "happyFace.xpm"
wxBitmap bitmap = wxBitmap( happyFace ); // assuming the variable name is "happyFace" inside the xpm
Then you will use bitmap object just like usual. Assuming that the file happyFace.xpm is available for compilation.

how to load qt compiled c++ code in maya?

Is there any way to load qt compiled c++ code in maya?
//example code
void MainWindow::on_pushButton_clicked()
{
ui->labell->setText("Hello");
}
actually i was created basic ui with text and push button, what i want is text should change to hello when i push button and i achieved that. so this connections were made with above code, after compiling this all works fine but when i load ui file in maya and i pushes the button text doesn't changes because actually code was written in c++. so, is there any alternative to load that code too along with ui file?
thank you,
Anvesh Chary
To load a .ui file in Maya, I've previously done this in python, I'm not sure about C++ but I don't believe maya interprets C++ directly anyway (I could be wrong there).
import maya.cmds as cmds
ve = cmds.about(version=True)
conv = "%s"%ve
versionOutput = float(conv[0:4])
def mayaVers():
cmds.warning("You're using Maya %s! You need to be using Maya 2011 or greater to be compatible with this script.\n" % conv);
def loadUIWindow():
if versionOutput >= 2011:
if (cmds.dockControl('dockUIWindow', exists=True)):
cmds.deleteUI('dockUIWindow')
scriptsDirectory = cmds.internalVar(usd=True)
UIWindow = cmds.loadUI(uiFile=scriptsDirectory + "/uifilename.ui")
dockSoftMod = cmds.dockControl('dockUIWindow',area="left", content='uiwindowname', label="")
else:
mayaVers()
loadUIWindow()
Here's how I've done it in the past, if you're just looking to source a UI file into the Maya session, this is how it can be done.
Obviously you'll need to either put your ui file in the scripts directory, or change the uiFilePath to your file.
Also, the content flag in the dockControl is important, this needs to be the name of the window or control that you're trying to dock. Let's say you have called your UI file wrapper 'win', the content flag would need to be the same.
EDIT
After you load the UI file, you can edit any element in the window if you know it's name.
cmds.button('ParentBtn', edit=1, command="parentObject()")
Hope this helps.

Programmatically selecting file in explorer

In my application I can programmatically open explorer and select a file using the following code:
void BrowseToFile(LPCTSTR filename)
{
CString strArgs;
strArgs = _T("/select,\"");
strArgs += filename;
strArgs += _T("\"");
ShellExecute(0, _T("open"), _T("explorer.exe"), strArgs, 0, SW_NORMAL);
}
My problem is that if I call this function a second time with a different file, but in the same folder, the selection in explorer does not change to the new file, but remains on the previous file.
For example, if I call my function with C:\path\to\file1.txt, a new explorer window will open and file1.txt will be selected. If I call my function a second time with C:\path\to\file2.txt, the existing explorer window will be activated, but the selection will still be on file1.txt.
Is there a way to force explorer to update the selection or a better way to accomplish this?
EDIT:
The behavior mentioned above was on Windows XP. It seems the behavior on Vista / Win7 is different. Each call will open a new instance of explorer and select the file.
My main goal is to replicate the Visual Studio option to Open Containing Folder of a document. This feature in Visual Studio behaves the same on XP, Vista, and Win7. It will not create a new instance if another instance with the same folder is already open, but it will update the selection to the new file.
If anybody knows how Visual Studio accomplishes this I would love to know about it.
Found the answer to my question. I need to use the shell function SHOpenFolderAndSelectItems. Here is the code for the function if anybody is ever interested:
void BrowseToFile(LPCTSTR filename)
{
ITEMIDLIST *pidl = ILCreateFromPath(filename);
if(pidl) {
SHOpenFolderAndSelectItems(pidl,0,0,0);
ILFree(pidl);
}
}
Try the '/n' option. This will, however, open a new folder - perhaps already opened. But, at least, the file you specify is selected.
/n,/select,<path_and_filename>
SHOpenFolderAndSelectItems always fails in my case and I can't figure out why. Btw, you must call CoInitialize/CoInitializeEx before calling this one.
In the case you outlined it appears the file window only selects the file when it's initialized instead of when activated.
Although this feels like a kludge, you could detect XP and only for that OS close the dialog using its handle and open a new one to target another file with.

Hardcoding the resources in application

I have some code which shows a simple dialog box and handles user action (written using plain WinAPI).
// Display dialog and handle user action
LRESULT choice = DialogBoxParam(NULL, MAKEINTRESOURCE(AP_IDD_DIALOG), NULL, (DLGPROC)DialogCallback, NULL);
Is there any way to hardcode the resource file dialog.rc, which is used to build the dialog ?(I would like to get rid of .rc files and I'm pretty sure there is a way, yet I don't know what it is :)
Edit
Also, does someone have any ideas on converting existing .rc files into hardcoded resources? Is this possible?
*.rc (resource) files are source code, they are compiled with the resource compiler and linked into your object (.exe/.dll)
You don't need to ship the resource file or have it present with your app to run it.
If you want to move to programmatically defined windows rather than templates then you might want to be looking at QT/wxWidgets. But thats a fair chunk of overhead for 1 dialog!
I'm surprised I couldn't find an existing app to do this sort of thing, enough hits on google with people trying to do this.
Ok, so the DLGTEMPLATE is a variable length blob of data, normally you let the dialog function pull it from the resource bundle for you, but instead you want to store it in your program.
You need to change your static lib to have a new function to decode some 'blob' back into the dlgtemplate, and you need to generate the blob. (or add the blob in your code without decoding which I don't want to think about right now)
The following code will give you the DLGTemplate data you need to imbed in your app. (cut from larger project)
HGLOBAL LoadResourceImpl(wchar_t *resource, wchar_t *type)
{
HRSRC handle = FindResource(hInstance, resource,type);
if (handle)
{
HGLOBAL hResource = LoadResource(hInstance, handle);
if (hResource)
return LockResource(hResource);
}
return 0;
}
DLGTEMPLATE * LoadDialog(wchar_t *resource)
{
return (DLGTEMPLATE *) LoadResourceImpl(resource,RT_DIALOG);
}
DLGTEMPLATE * LoadDialog(int resource)
{
return (DLGTEMPLATE *) LoadResourceImpl(MAKEINTRESOURCE(resource),RT_DIALOG);
}
Make an app that includes your resource - use the appropriate LoadDialog to get the data.
Now "write out" that blob in a format to include in your app -
step 1 - find out how much data there is by traversing the structure to find the total size including all the controls (control count is in DLGTEMPLATE::cdit)
step 2 - convert the data to something you can compile into your code - like HEX
Add to your static library a new 'HEX' to DLGTEMPLATE method and the hex string you made using the other app.
Can we hard code the .res file into the program?
the resource compiler converts .rc into .res
use a hex dump tool (eg. winhex) to translate the .res into bytes array
(represented in C source code).
add the source code file in the project and compile in the executable.
locate the dialog resource position from the array and use DialogBoxIndirect.
DialogBoxParamIndirect can be used instead. It takes as a parameter the dialog template. Raymond Chen's blog has an example of building a dialog box at runtime rather than from a resource using the DialogBox*Indirect API's.
Per MSDN, dialog box resources are basically composed of the DLGTEMPLATE and DLGITEMTEMPLATE structures. So you should be able to use the resource API's (FindResource, LoadResource, and LockResource) to get at the underlying bits of an existing dialog resource, and embed that within your code.
Note that this is a lot more painful than using the .rc file. It's much more difficult to make changes to your layout, and it's also much less localizable, since localization would now require a code change to update the template in code.
If it's a simple dialog, why use the DLGTEMPLATE at all?
Nothing stops you from simply doing ::CreateWindow'ing those controls directly. If it's a simple dialog with 2-3 buttons and a couple text fields, simply call ::CreateWindow, passing in the window class of whatever common control you're using.
This is essentially what the DialogXxxxx functions do anyway. DLGTEMPLATE is a convenience for declaratively laying out your forms, and having the boilerplate make the appropriate CreateWindow calls, etc.

Loading Nib and Displaying Window in Objective C++

I am trying to load a Nib from a C++ constructor with Objective C++. I have searched and found enough examples to get some code together but it doesn't display the window. Or any windows for that matter.
Here is an example of the contructor:
JokeSystem::JokeSystem() : fileSystem("/Library/Application Support/Jokes/")
{
try
{
randSystem = new RandSelect<std::string>
(fileSystem.getAllFileContents("%\n"));
}
catch (std::ifstream::failure)
{
NSWindowController * errorWindowControl = [[NSWindowController alloc]
initWithWindowNibName:#"ErrorWindow"];
[errorWindowControl showWindow: nil];
}
}
The purpose of the contructor is to load the contents of a directory into a string. What I am try to do is display the error window when the files fail to open.
ErrorWindow.nib has a single window with an OK button and a NSTextView for the error, I set up a NSWindowController in the nib and connected it to the window.
My only link has been that most examples show this [errorWindowControl showWindow: self];
rather than showWindow: nil but because this is a C++ constructor I it doesn't have self and this doesn't work.
If it matters this contructor is called from the awakeFromNib method of the MainMenu.nib's primary NSObject.
Thanks
A bit of an odd way to approach Cocoa. I would encourage you to step back, learn Objective-C and then write your application with an Objective-C based Cocoa UI layer on top of whatever backing store or model layer you have.
In any case, there isn't anything particularly wrong with that code (save for the odd design).
The first thing to check is the return value of -initWithWindowNibName:. Is errorWindowControl actually non-nil? If it is nil, then the NIB failed to load.
How are you writing the Cocoa application itself? Standard app bundle using Xcode, I hope?
Also, you shouldn't be hardcoding the path to /Library/Application Support/. Actually, your application shouldn't use that directory as the only storage location; many users won't have write access to that directory and won't be able to install your app without administrator access.