MFC Automation how to implement RemoveDocument OnCloseDocument - com

I have an MFC MDI Application and I am trying to implement Automation with it. I am trying to create a RemoveDocument. How is that done? OnCloseDocument is causing problems. Is there a "standard" for doing that?

You could just send a WM_CLOSE message to the Document's frame.
Edit: You could try sending it to the document's view instead. You can get all views that point to a given document by calling:
POSITION pos = pDoc->GetFirstViewPosition();
while( pos != NULL )
{
CView* pView = GetNextView( pos );
}
I "think" that should do the trick ...

Related

Getting Actual Placement of a Flyout

I have a flyout that appears near the cursor when a particular user input is triggered.
According to the docs, the Flyout.Placement property is only a preference and does not necessarily reflect the position of the flyout.
I expect the framework to call GetFlyoutPlacement to determine the actual placement. I want to know what the actual placement is so that I can add a little arrow pointing at the cursor position, something like shown in the following:
Is my only option to make the call to GetFlyoutPlacement myself (triggered on the Flyout.Opening event), or is there some more convenient way to do this?
My calls on GetFlyoutPlacement and GetFlyoutPlacementTargetInfo resulted in Error HRESULT E_FAIL has been returned from a call to a COM component. which didn't leave me very much to go on, so I just ended up implementing what I imagine is the logic behind those functions:
public static FlyoutPlacementMode GetActualFlyoutPlacement(
Rect placementTarget,
Size flyoutSize,
FlyoutPlacementMode preferredPlacement )
{
Rect ViewArea = Window.Current.Bounds;
ViewArea.X = 0; // may have non-zero offset for multi-monitor setups
ViewArea.Y = 0; // but we are only interested in offset relative to app view area
switch (preferredPlacement)
{
case FlyoutPlacementMode.Right:
if (desiredSize.Width < ViewArea.Width - placementTarget.Right) return FlyoutPlacementMode.Right;
if (desiredSize.Width < placementTarget.Left) return FlyoutPlacementMode.Left;
if (desiredSize.Height < placementTarget.Top) return FlyoutPlacementMode.Top;
return FlyoutPlacementMode.Bottom;
case FlyoutPlacementMode.Left:
...
}
}
Checkout the approach I suggested here. I believe it is better, because instead of guessing the internal placement algorithm it just compares the absolute coordinates of the flyout and the target element.

AIR native extension: Can I call ActionScript 3 method from C/Objective-C?

I have an AIR application that uses a native extension to create a series of dialogs the user navigates through. After the user navigates through the dialogs, I need the C/Objective-C side to notify the AIR app that the user finished as well as forward the series of choices the user made.
Is that possible?
IE: the C/ObjC equivalent of
public function evokeMyASMethod(choice0:int,choice1:int):Boolean
{
// context opens the native extension to the AS3 side
var success:Boolean = context.call("myASMethod", choice0, choice1) as Boolean;
return success;
}
An alternate solution is to start a timer in ActionScript that pings the native extension periodically to check whether the user has finished and fetch the values, but that seems so messy that I think I must be missing something obvious.
Any help is much appreciated. Thanks!
What you'll need to do is dispatch "status" events from the native code and then listen for them in your AS3 code.
So firstly in your AS3 code add a listener to your extension context:
context.addEventListener( StatusEvent.STATUS, onStatus);
private function onStatus( event:StatusEvent ):void
{
trace( "code = " + event.code );
trace( "level = " + event.level );
}
The code and level variables are two strings you can pass back from your native code. In your ObjC code you'll use the FREDispatchStatusEventAsync function to fire an event back to your AS3 code:
FREDispatchStatusEventAsync( yourFreContext, (const uint8_t*)"code", (const uint8_t*)"level" );
You just need to change the "code" and "level" strings as you see fit and process them in your onStatus handler.
More information here:
http://help.adobe.com/en_US/air/extensions/WSb464b1207c184b143961a5e412937b5d5c6-7ffc.html
http://help.adobe.com/en_US/air/extensions/WSb464b1207c184b14-62b8e11f12937b86be4-7ff5.html

Windows 8 app: How to pass a parameter on GoBack()?

There are a lot of samples showing how to pass a parameter on navigating to a page in Window 8 (WinRT). But I could not find any hint for passing parameters going back.
Situation: The user navigates to a details page of same data. The data is passed to the page by
Frame.Navigate(typeof(DedtailsPage), data);
How can I pass back the changed data on GoBack()?
Store the reference to data somewhere and retrieve it when you navigate back?
Also note that it's best not to pass objects other than simple strings or values between pages, since only simple types are supported for storing frame navigation state in case your app gets suspended.
I know, that this is a very bad idea, but usualy I use this:
To write:
Frame rootFrame = Window.Current.Content as Frame;
rootFrame.Tag = myObject1;
To read:
Frame rootFrame = Window.Current.Content as Frame;
var myObject2 = rootFrame.Tag;
I've made another choice to handle this.
Keep in mind that I'm a Xamarin developer (not Forms!) so i was looking for a solution which was similar for all platforms: iOS, Android and Windows.
I am a great fun of events, rather than passing objects or storing globals.
So the best choice to pass data from PageB (the child) to PageA (the parent) is to communicate via events.
Some notes: In iOS and Android, when you navigate from a "page" to "page" you can do this by passing an instance of the target object you want to navigate to. In iOS you create an instance of a custom UIViewController. In Android you create an instance of a custom Fragment. Doing this allow you to attach events handler to your instances.
An example:
var controller = new ExtrasViewController();
controller.ExtraSelected += ExtrasFragment_ExtraSelected;
controller.ExtrasCleared += ExtrasFragment_ExtrasCleared;
this.NavigationController.PushViewController(controller, false);
In WinRT Apps you are only allowed to pass "types" of target page to navigate to. So the only way to attach event handlers to your page instance is to use the OnNavigatedFrom method from the calling page. So suppose you are in PageA and want to attach some event handlers to your PageB, before it become active, simply write in your PageA "code behind":
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
var page = e.Content as ExtraBody;
if(page != null)
{
page.ExtraSelected += ExtrasFragment_ExtraSelected;
page.ExtrasCleared += ExtrasFragment_ExtrasCleared;
}
}

Accessing the Thunderbird message when closing a message tab / window

We have developed a Thunderbird (11) plugin that allows us to save the content of a message to disk. Now we are extending this extension to allow automatic processing of a message when you close it. We run into a number of issues:
We cannot find a way to hook into a 'close tab' event. We are also having trouble getting the Message URI of the currently open tabs (we are trying catching click and keyboard events now). This information does not appear to be available in the DOM of the tab container.
Is there a way to detect closing of a mail message tab or window in a generic way, together with retrieving the URI of the closed mail message for further processing?
We have looked at the documentation of the tab container, the NsIWindowMediator, tried various event listeners, but no luck so far.
Edit: We are getting some results using the most recently closed tabs list. Not a very elegant solution but at least we have a reference to the tab. Now we only have to get the URI to the message that was contained inside the tab.
We cannot find a way to hook into a 'close tab' event.
The (badly documented) <tabmail> element allows registering tab monitors. Something like this should work:
var tabmail = document.getElementById("tabmail");
var monitor = {
onTabClosing: function(tab)
{
...
}
};
tabmail.registerTabMonitor(monitor);
We are also having trouble getting the Message URI of the currently open tabs
The <tabmail> element has a property tabInfo containing information on the currently open tabs. You probably want to look only at the tabs where mode.name is "message" (there is a bunch of other modes as well, e.g. "folder" or "contentTab"). This mode has a getBrowser() method, so something like this should do:
var tabmail = document.getElementById("tabmail");
for (var i = 0; i < tabmail.tabInfo.length; i++)
{
var tab = tabmail.tabInfo[i];
if (tab.mode.name == "message")
alert(tab.mode.getBrowser().currentURI.spec);
}
Edit: As Peter points out in the comments, the approach to get the URI for a message will only work the currently loaded message - all tabs reuse the same browser element for the mail messages. Getting the URI properly is more complicated, you have to get the nsIMsgDBHdr instance for the message via TabInfo.folderDisplay.selectedMessage and then use nsIMsgFolder.getUriForMsg() to construct the URI for it:
var tabmail = document.getElementById("tabmail");
for (var i = 0; i < tabmail.tabInfo.length; i++)
{
var tab = tabmail.tabInfo[i];
if (tab.mode.name != "message")
continue;
var message = tab.folderDisplay.selectedMessage;
alert(message.folder.getUriForMsg(message));
}
For the second part of the question:
The following example code will at provide you the msgDBHdr objects of all opened tabs. You should do some checks on the type to avoid accessing a message in a calendar tab.):
tabInfos = window.document.getElementById("tabmail").tabInfo;
for (i = 0; i < tabInfos.length; i++) {
msgHdr = tabInfos[i].folderDisplay.selectedMessage;
alert(
msgHdr.mime2DecodedSubject+"\n"
+msgHdr.messageId+"\n"
+"in view type "+tabInfos[i].mode.type
);
}
The tabinfo entries have some further interesting information. Just open the ErrorConsole and run
top.opener.window.document.getElementById("tabmail").tabInfo[0].toSource()
and read through it carefully.

Change applicationbar buttonicon at runtime

I'm developing a WP7 app and the application needs to change the icon of a button on the application bar given the state of a request.
I have tried:
if (App.Servers[index].ServerState == "Enabled")
{
DetailsAppBar.btnStart.IconUri = new Uri("/AppBar/appbar.stop.rest.png");
}
else
{
DetailsAppBar.btnStart.IconUri = new Uri("/AppBar/appbar.transport.play.rest.png");
}
This doesn't give me an error in the code, but it can't compile....
any hints to do this is appreciated :)
thanks
ApplicationBar is a special control that does not behave as other Silverlight controls (see Peter Torr's post on the subject). One of the consequences is that names given in XAML to app bar buttons generate fields in code-behind that are always null.
I'm guessing that in your case the btnStart field in DetailsAppBar is set to null, and thus trying to set its IconUri property results in a NullReferenceException being thrown.
To access a button in an application bar, you must instead reference it by its zero-based index in the buttons list. For instance, the code below returns a reference to the third button in the app bar:
button = (IApplicationBarIconButton)ApplicationBar.Buttons[2];
figured it out...
((ApplicationBarIconButton)ApplicationBar.Buttons[2]).IconUri = new Uri("/AppBar/appbar.stop.rest.png",UriKind.Relative);
did the trick :)