Exchange data from Microsoft Business Central to JavaScript - microsoft-dynamics

Curerntly I'am working on a scanner that inputs data into BC fields. The communication between the device and the software is in javascript. I can send data from JS to BC with
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('BarcodeRead',[BCode] );
but I couldn't figure out how to send data back to JS. (The reader has a screen, and I need to display warehouse inventory on it based on BC data).
My current best guess would be to send data with STREAMS to a .txt file, and the JS code read from that. But that would be slow and not so reliable in my opinion.

As you know allready that InvokeExtensibilityMethod can trigger events on the BC side, you know that you need a Control Add-In.
On the Microsoft Docs page about Control Add-Ins, there is an example which shows you how to call JS functions from BC:
// The procedure declarations specify what JavaScript methods could be called from AL.
// In main.js code, there should be a global function CallJavaScript(i,s,d,c) {Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('CallBack', [i, s, d, c]);}
procedure CallJavaScript(i: integer; s: text; d: decimal; c: char);
In BC lingo, procedures are kind of the opposite of events.

Related

How to monitor clipboard changes in X11 Windows?

I am pretty much exhausted all the possibilities of finding an X11 API to perform the following thing.
I have a thread which is trying to monitor for an event or notification to know when anything is copied into clipboard by any X11 client. I do not want to monitor a specific Atom Target (clipboard format), but generally looking for changes in clipboards.
Once, I know that something has changed in the clipboard, I can dive in and perform XConvertSelection() on all the target formats (I want to request server to give me all the possible ways to convert the copied data), and futher process them into SelectionRequest event.
Again, I want to generally get request for all the formats (thinking to enumerate between 1 to 1000 to check target Atoms), and not register changes for one specific format. Based on response from the server, if a particular atom is absent, I can check None as the property member, or else store other target Atom Names in a list.
Can anyone help me with how to monitor for changes in Clipboard? Also, does iterating 1 to 1000 will guarantee exhaustive search of all possible format? Or is there a better way to do just that?
To monitor changes, use XFixes. With XCB it is used like:
// Enable XFixes
auto xfixes = xcb_get_extension_data(connection, &xcb_xfixes_id); // do not free!
ev_selection_change_notify = xfixes->first_event + XCB_XFIXES_SELECTION_NOTIFY;
auto *version = xcb_xfixes_query_version_reply(xcb_xfixes_query_version(connection, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION));
// Subscribe to clipboard notifications
xcb_xfixes_select_selection_input(connection, root, clipboard, XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER);
// Event loop:
auto *event = xcb_poll_for_event(connection);
int etype = event->response_type & 0x7f;
if (etype == ev_selection_change_notify) {
auto *notification = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(event);
...
}
...
In Xlib it should be similar.
To check the list of available targets, don’t loop to 1000! Simply query the TARGETS target, it should give you the list of valid targets for the clipboard content.
There is a caveat, though: instead of “the” clipboard, X11 allow applications to use “selections” which can be tagged by arbitrary atoms. Of those CLIPBOARD is of primary interest but PRIMARY and (rarely used) SECONDARY are also there, as well as arbitrary selections for “private communication”.
Reference: https://www.x.org/releases/X11R7.7/doc/xorg-docs/icccm/icccm.html#Use_of_Selection_Atoms

Does the WinRT Clipboard History only support text and images?

I'm making a C++/WinRT app that makes use of the Window 10 clipboard history but for some reason I can only grab text and images.
My code is a bit like this..
auto history = Clipboard::GetHistoryItemsAsync().get();
if (history.Status() == ClipboardHistoryItemsResultStatus::Success)
{
auto historyItemList = history.Items();
for (const auto& historyitem : historyItemList)
{
//Works
if (dataPackageView.Contains(StandardDataFormats::Text()))
{
GetClipboardText(dataPackageView);
}
//Works
if (dataPackageView.Contains(StandardDataFormats::Bitmap()))
{
GetClipboardBitmap(dataPackageView);
}
//Never triggers
if (dataPackageView.Contains(StandardDataFormats::Html()))
{
GetClipboardHtml(dataPackageView);
}
//Never triggers
if (dataPackageView.Contains(StandardDataFormats::StorageItems()))
{
GetClipboardStorageItems(dataPackageView);
}
//etc..
I'd like to make use of the other dataformats. EG: For StorageItems, I expected if I CTRL+C an item from my desktop or if I did it programatically with
dataPackage.SetStorageItems({ std::begin(files), std::end(files) });
Clipboard::SetContent(dataPackage);
Clipboard::Flush();
The file would end up in the clipboard history so I could handle it like in the first snippet. But the file never appears in the returned Clipboard::GetHistoryItemsAsync() container. I also don't see the file in the history viewer when you press WIN+V.
So what i'm wondering is;
Does Windows 10 clipboard history "only" support raw text and images? can I not make use of the other dataformat properties? (ApplicationLink, Html, Rtf, StorageItems, Uri, Weblink etc)
I gave StorageItems as an example but it happens with the other formats too. If I CTRL+C a weblink (such as: https://stackoverflow.com/questions/ask), I expected dataPackageView.Contains(StandardDataFormats::WebLink()) Or Uri to trigger, but they don't
If the clipboard history can support other formats, how do you actually make use of it?
Edit:
Forgot to add. When I programatically added a StorageItem to the clipboard I also tried it like below. Don't know why I can't add strings to an IVector though.
auto options = ClipboardContentOptions();
auto formats = Windows::Foundation::Collections::IVector<hstring>();
formats.Append(StandardDataFormats::StorageItems()); //Unhandled Exception
options.IsAllowedInHistory(true);
options.IsRoamable(true);
options.HistoryFormats() = formats;
options.RoamingFormats() = formats;
Clipboard::Clipboard::Clear();
Clipboard::SetContentWithOptions(dataPackage, options);
Clipboard::Flush();
As observed by my esteemed colleague Faywang - MSFT, Windows' clipboard history and cloud clipboard sync implementation supports only a limited number of clipboard data formats, and this is reflected in the UWP clipboard API in the Windows Runtime Clipboard class.
It's important to remember that what clipboard formats are supported by clipboard history is not a contractual detail of clipboard history. Please keep that in mind when you read on:
As of Windows 10 version 2004 (aka build 19041, aka the May 2020 update), clipboard history supports the following clipboard data formats defined in StandardDataFormats:
Plain text: StandardDataFormats.Text
Various URI formats: StandardDataFormats.Uri, StandardDataFormats.WebLink, and StandardDataFormats.ApplicationLink
HTML clipboard format: StandardDataFormats.Html
Bitmaps: StandardDataFormats.Bitmap
For compatibility with classic desktop applications (aka Win32 apps), clipboard history also supports a few clipboard data formats whose names are not in StandardDataFormats, but which the Windows system can auto-convert to and from the above-listed StandardDataFormats formats when needed by an app trying to paste a particular format.
Clipboard history does not support any other custom or well-known clipboard formats.
Given the above, the only thing I see in your results that seems strange is that your app doesn't appear to be reading the HTML format. I don't know of any Windows implementation bugs in this area - try fiddling with your code some more, and if you still have trouble, I'd definitely encourage you to post another question, or contact us at Microsoft another way (such as through Feedback Hub).
I do observe that the Microsoft documentation around clipboard history from a conceptual technical perspective is lacking. I'd also encourage you to file GitHub issues against the places where clipboard history is documented, such as https://github.com/MicrosoftDocs/winrt-api - we're always listening.

DCMTK Understand the "DIMSE No valid Presentation Context ID" error

I'm currently developing a simple application for querying/retrieving data on a PACS. I use DCMTK for this purpose, and a DCM4CHEE PACS as test server.
My goal is to implement simple C-FIND queries, and a C-MOVE retrieving system (coupled with a custom SCP to actually download the data).
To do so, I've created a CustomSCU class, that inherits the DCMTK DcmSCU class.
I first implemented a C-ECHO message, that worked great.
Then, I tried to implement C-FIND requesting, but I got the error "DIMSE No valid Presentation Context ID" (more on that in the next paragraph) from my application, but no other log from DCM4CHEE. I've then used the command tool findscu (from dcmtk) to see if there was some configuration issue but the tool just worked fine. So in order to implement my C-FIND request, I've read the source of findscu (here) and adapted it in my code (meaning that i'm not using DcmSCU::sendCFindRequest but the class DcmFindSU).
But now, i'm facing the same problem with C-MOVE request. My code is pretty straight-forward :
//transfer syntaxes
OFList<OFString> ts;
ts.push_back(UID_LittleEndianExplicitTransferSyntax);
ts.push_back(UID_BigEndianExplicitTransferSyntax);
ts.push_back(UID_LittleEndianImplicitTransferSyntax);
//sop class
OFString pc = UID_MOVEPatientRootQueryRetrieveInformationModel;
addPresentationContext(pc, ts);
DcmDataset query;
query.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "PATIENT");
query.putAndInsertOFStringArray(DCM_PatientID, <ThePatientId>);
OFCondition condition = sendMOVERequest(findPresentationContextID(pc, ""), getAETitle(), &query, nullptr);
return condition.good();
I've also tried using UID_MOVEStudyRootQueryRetrieveInformationModel instead of UID_MOVEPatientRootQueryRetrieveInformationModel, with the same result : my application shows the error
DIMSE No valid Presentation Context ID
As I understand, a presentation context is concatenation of one or more transfer syntax and one SOP class. I read that the problem could come from the PACS that won't accept my presentation contexts. To be sure, I used the movescu tool (from DCMTK). It worked, and I saw this in the logs from de server DCM4CHEE :
received AAssociatedRQ
pc-1 : as=<numbers>/Patient Root Q/R InfoModel = FIND
ts=<numbers>/Explicit VR Little Endian
ts=<numbers>/Explicit VR Big Endian
ts=<numbers>/Implicit VR Little Endian
That means that the movescu tool does a find before attempting an actual move ?
Therefore, I changed my application context creation with :
OFList<OFString> ts;
ts.push_back(UID_LittleEndianExplicitTransferSyntax);
ts.push_back(UID_BigEndianExplicitTransferSyntax);
ts.push_back(UID_LittleEndianImplicitTransferSyntax);
OFString pc1 = UID_FINDPatientRootQueryRetrieveInformationModel;
OFString pc = UID_MOVEPatientRootQueryRetrieveInformationModel;
addPresentationContext(pc1, ts);
addPresentationContext(pc, ts);
(also tried study root)
But this didn't do the trick.
The problem seems to lie on the client side, as findPresentationContextID(pc, ""); alwasy return 0, no matter what.
I don't feel like it's possible to adapt the code of the movescu tool, as it appears to be very complex and not adequat for simple retrieve operations.
I don't know what to try. I hope someone can help me understand what's going on. That's the last part of my application, as the storage SCP already works.
Regards
It looks like you are not negotiating the association with the PACS.
After adding the presentation contexts and before sending any command, the SCU must connect to the PACS and negotiate the PresentationContexts with DcmSCU::initNetwork and then DcmSCU::negotiateAssociation.

Dynamic messages with gettext (AngularJS)

I have a application with a Django backend and an AngularJS front-end.
I use the angular-gettext plugin along with Grunt to handle translations.
The thing is, I sometimes received dynamic strings from my backend through the API. For instance a MySQL error about a foreign key constraint or duplicate key entry.
How can I add this strings to the .pot file or non harcoded string in general ?
I've tried to following but of course it cannot work :
angular.module('app').factory('HttpInterceptor', ['$q', '$injector', '$rootScope', '$cookieStore', 'gettext', function ($q, $injector, $rootScope, $cookieStore, gettext) {
responseError: function (rejection) {
gettext('static string'); //it works
gettext(rejection.data.error); //does not work
$rootScope.$emit('errorModal', rejection.data);
}
// Return the promise rejection.
return $q.reject(rejection);
}
};
}]);
})();
One solution I could think of would be to write every dynamic strings into a JSON object. Send this json to server and from there, write a static file containing these strings so gettext can extract them.
What do you suggest ?
I also use angular-gettext and have strings returned from the server that need to be translated. We did not like the idea of having a separate translation system for those messages so we send them over in the default language like normal.
To allow this to work we did two things. We created a function in our backend which we can call to retrieve all the possible strings to translate. In our case it's mainly static data that only changes once in a while. Ideally this would be automated but it's fine for now.
That list is formatted properly through code into html with the translate tag. This file is not deployed, it is just there to allow the extraction task to find the strings.
Secondly we created a filter to do the translation on the interpolated value, so instead of translating {{foo}} it will translate the word bar if that's was the value of foo. We called this postTranslate and it's a simple:
angular
.module('app')
.filter('postTranslate', ['gettextCatalog', function (gettextCatalog) {
return function (s) {
return gettextCatalog.getString(s);
};
}]);
As for things that are not in the database we have another file for those where we manually put them in. So your error messages may go here.
If errors are all you are worried about though, you may rather consider not showing all the error messages directly and instead determine what user friendly error message to show. That user friendly error message is in the front end and therefore circumvents all of this other headache :)

flex : How to import .fla file into the flex application

I have one .fla file sent by some one. I want to import this file into my actionscript project using flex builder and I need to work on frames of the fla file . How to do this. I am very new to flex . I am searching this in internet with of no results. please help me.
You cannot edit a flash file directly within the Flash Builder (i.e. Flex) IDE. You can however access the published swf from within Flex.
A common use is to access assets from a library swf - http://www.bit-101.com/blog/?p=853. But I assume you are interested in accessing specific frames in the interactive. Different options are possible :
use localConnection - http://fbflex.wordpress.com/2008/06/12/passing-data-from-flash-to-flex-and-back/
load the resulting swf into a loader object and navigate to frame - SWFLoader starts to play SWF without the loading being complete
load the resulting swf into a loader object and communicate via events
<mx:SWFLoader id="embeddedFlash" source="path/to/file.swf" complete="onLoaderComplete(event)"/>
<mx:Script>
<![CDATA[
private function onLoaderComplete(event:Event)
{
// the swf file needs to be fully loaded before these calls are made
if(embeddedFlash.content)
{
// 2 - navigate to frame
var mc:MovieClip = MovieClip(embeddedFlash.content);
mc.gotoAndPlay(0);
// 3 - communicate via events
embeddedFlash.content.addEventListener("nextButtonClick", onNextClick);
embeddedFlash.content.dispatchEvent(new Event("changeOptions", {/* pass on data */}));
}
}
]]>
</mx:Script>