A descendant of TStyledPresentationProxy has not been registered for class - c++

I have a custom grid control that inherits from TGrid called TFmGrid. This control was working fine in Rad Studio 10 Seattle Update One. I recently upgraded to 10.1 Berlin and started noticing this error message showing up on my TFmGrid controls both when I run the application and in the designer:
A descendant of TStyledPresentationProxy has not been registered for class TFmGrid. Maybe it is necessary to add the FMX.Grid.Style module to the uses section
The image below shows how the error message shows up on my grid controls:
I started by doing as the message suggests, and adding #include <FMX.Grid.Style.hpp> to the header file of my TFmGrid control, however this seems to have done nothing.
So as far as trying to register a decendant of TStyledPresentationProxy I am not exactly sure where to start. I found this documentation about a method which:
Attempts to register the presentation proxy class with the specified name or the specified combination of control class and control type.
So I assume I need to use this method or at least something similar, but I don't understand how I am supposed to go about calling this method.
But then that brings up the question of WHERE do I call this code?
My custom control has a method in its namespace called Register() which I believe was autogenerated by the IDE when the control was created:
namespace Fmgridu
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TFmGrid)};
RegisterComponents(L"Kalos FM Controls", classes, 0);
}
}
Do I need to call something in there to register a decendant of TStyledPresentationProxy? What is the proper way to go about this?

Just override virtual method DefinePresentationName in you TfmGrid and return name of presentation name for grid:
function TfmGrid.DefinePresentationName: string;
begin
Result := 'Grid-' + GetPresentationSuffix;
end;
Fm registers presentation by string name and uses class name for it, so if you create new component (based on existed) you automatically change classname, so system cannot find presentation for you. There are two solution:
Said that you will use presentation from TGrid (DefinePresentationName)
Register existed presentation for you class (look at the initialization section of FMX.Grid.Style.pas)
P.S. Year ago i wrote article about it in common eNew approach of development of FireMonkey control “Control – Model – Presentation”. Part 1 I hope it will help you

It's simple :
Just put "StyleBook" component to your form

I had the same issue with a test component I was developing.
Complementing Yaroslav Brovin's speech, I solved the problem by adding the class register in the initialization and finalization clauses at the end of the unit, like this:
initialization
TPresentationProxyFactory.Current.Register(<COMPONENT CLASSNAME HERE>, TControlType.Styled, TStyledPresentationProxy<TStyledGrid>);
finalization
TPresentationProxyFactory.Current.Unregister(<COMPONENT CLASSNAME HERE>, TControlType.Styled, TStyledPresentationProxy<TStyledGrid>);
In my case looks like this:
initialization
TPresentationProxyFactory.Current.Register(TSGrid, TControlType.Styled, TStyledPresentationProxy<TStyledGrid>);
finalization
TPresentationProxyFactory.Current.Unregister(TSGrid, TControlType.Styled, TStyledPresentationProxy<TStyledGrid>);
PS: Don't forget to declare the FMX.Presentation.Factory,
FMX.Presentation.Style and FMX.Grid.Style units in the uses clause

Related

Acumatica - Problem with data displaying in custom field even though saved to database

I created a custom date field in the opportunity screen. The field shows up just as expected. I enter a date save the record, go out, go back in and the date is no longer there. However, when I query the database, the column is there and there is a data in the column. So, even though the date is being stored in the database it is not displaying it in the screen or when I added that value to the generic inquiry it is also blank. I am not a programmer but it seems like that should’ve been an easy thing to do. I found some references on the web of this type of problem but was hoping there was a more straightforward fix than what those appeared, as they were more programming than I am comfortable at this point.
I found many web pages explaining how to do this seemingly simple thing using the customization tools. Not sure what I'm missing.
I am running fairly recent version of 2019R1.
Any help would be appreciated!
Response from an Acumatica support person.. Evidently they changed some things with 2018R1. See comments/answers below from support. Image of the change I made in the customization tool is also below. After making this change the custom field worked as desired.
After reviewing it into more details, it sounds that it could be related to the new implementation of PXProjection on that DAC.
Unlike ver. 2017 R2, some DAC like the PX.Objects.CR.CROpportunity DAC were implemented as a regular Data Access Class:
[System.SerializableAttribute()]
[PXCacheName(Messages.Opportunity)]
[PXPrimaryGraph(typeof(OpportunityMaint))]
[CREmailContactsView(typeof(Select2<Contact,
LeftJoin<BAccount, On<BAccount.bAccountID, Equal<Contact.bAccountID>>>,
Where2<Where<Optional<CROpportunity.bAccountID>, IsNull, And<Contact.contactID, Equal<Optional<CROpportunity.contactID>>>>,
Or2<Where<Optional<CROpportunity.bAccountID>, IsNotNull, And<Contact.bAccountID, Equal<Optional<CROpportunity.bAccountID>>>>,
Or<Contact.contactType, Equal<ContactTypesAttribute.employee>>>>>))]
[PXEMailSource]//NOTE: for assignment map
public partial class CROpportunity : PX.Data.IBqlTable, IAssign, IPXSelectable
{
...
}
In version 2018 R1(and later) the PX.Objects.CR.CROpportunity DAC is a projection over the PX.Objects.CR.Standalone.CROpportunity and PX.Objects.CR.Standalone.CROpportunityRevision DACs:
[System.SerializableAttribute()]
[PXCacheName(Messages.Opportunity)]
[PXPrimaryGraph(typeof(OpportunityMaint))]
[CREmailContactsView(typeof(Select2<Contact,
LeftJoin<BAccount, On<BAccount.bAccountID, Equal<Contact.bAccountID>>>,
Where2<Where<Optional<CROpportunity.bAccountID>, IsNull, And<Contact.contactID, Equal<Optional<CROpportunity.contactID>>>>,
Or2<Where<Optional<CROpportunity.bAccountID>, IsNotNull, And<Contact.bAccountID, Equal<Optional<CROpportunity.bAccountID>>>>,
Or<Contact.contactType, Equal<ContactTypesAttribute.employee>>>>>))]
[PXEMailSource]//NOTE: for assignment map
[PXProjection(typeof(Select2<Standalone.CROpportunity,
InnerJoin<Standalone.CROpportunityRevision,
On<Standalone.CROpportunityRevision.opportunityID, Equal<Standalone.CROpportunity.opportunityID>,
And<Standalone.CROpportunityRevision.revisionID, Equal<Standalone.CROpportunity.defRevisionID>>>>>), Persistent = true)]
public partial class CROpportunity : IBqlTable, IAssign, IPXSelectable
{
...
}
Because of that change, it's now required to declare 2 extension classes, one for Standalone.CROpportunity (normal DAC) and the CROpportunity (PXProjection).
On the PXProjection DAC Extension, please remind to add BqlField to the correspondent field on the Standalone DAC, Ex.: BqlField = typeof(CROpportunityStandaloneExt.usrTest)
public class CROpportunityExt : PXCacheExtension<PX.Objects.CR.CROpportunity>
{
#region UsrTest
[PXDBDecimal(BqlField = typeof(CROpportunityStandaloneExt.usrTest))]
[PXUIField(DisplayName="Test Field")]
public virtual Decimal? UsrTest { get; set; }
public abstract class usrTest : IBqlField { }
#endregion
}
Please find more information on this article below:
Custom field on CROpportunity doesn't display saved value since upgrading from 6.10 or 2017R2 to 2018R1
change made in customization tool

Getting ColdFusion-Called Web Service to Work with JavaLoader-Loaded Objects

Is it possible to use JavaLoader to get objects returned by CF-called web services, and JavaLoader-loaded objects to be the same classpath context? I mean, without a lot of difficulty?
// get a web service
ws = createObject("webservice", local.lms.wsurl);
// user created by coldfusion
user = ws.GenerateUserObject();
/* user status created by java loader.
** this api provider requires that you move the stubs
** (generated when hitting the wsdl from CF for the first time)
** to the classpath.
** this is one of the stubs/classes that gets called from that.
*/
UserStatus = javaLoader.create("com.geolearning.geonext.webservices.Status");
// set user status: classpath context clash
user.setStatus(UserStatus.Active);
Error:
Detail: Either there are no methods with the specified method name and
argument types or the setStatus method is overloaded with argument
types that ColdFusion cannot decipher reliably. ColdFusion found 0
methods that match the provided arguments. If this is a Java object
and you verified that the method exists, use the javacast function to
reduce ambiguity.
Message: The setStatus method was not found.
MethodName setStatus
Even though the call, on the surface, matches a method signature on user--setStatus(com.geolearning.geonext.webservices.Status)--the class is on a different classpath context. That's why I get the error above.
Jamie and I worked on this off-line and came up with a creative solution :)
(Apologies for the long answer, but I thought a bit of an explanation was warranted for those who find class loaders as confusing as I do. If you are not interested in the "why" aspect, feel free to jump to the end).
Issue:
The problem is definitely due to multiple class loaders/paths. Apparently CF web services use a dynamic URLClassLoader (just like the JavaLoader). That is how it can load the generated web service classes on-the-fly, even though those classes are not in the core CF "class path".
(Based on my limited understanding...) Class loaders follow a hierarchy. When multiple class loaders are involved, they must observe certain rules or they will not play well together. One of the rules is that child class loaders can only "see" objects loaded by an ancestor (parent, grandparent, etcetera). They cannot see classes loaded by a sibling.
If you examine the object created by the JavaLoader, and the other by createObject, they are indeed siblings ie both children of the CF bootstrap class loader. So the one will not recognize objects loaded by the other, which would explain why the setStatus call failed.
Given that a child can see objects loaded by a parent, the obvious solution is to change how the objects are constructed. Structure the calls so that one of the class loaders ends up as a parent of the other. Curiously that turned out to be trickier than it sounded. I could not find a way to make that happen, despite trying a number of combinations (including using the switchThreadContextClassLoader method).
Solution:
Finally I had a crazy thought: do not load any jars. Just use the web service's loader as the parentClassLoader. It already has everything it needs in its own individual "class path":
// display class path of web service class loader
dynamicLoader = webService.getClass().getClassLoader();
dynamicClassPath = dynamicLoader.getURLS();
WriteDump("CLASS PATH: "& dynamicClassPath[1].toString() );
The JavaLoader will automatically delegate calls for classes it cannot find to parentClassLoader - and bingo - everything works. No more more class loader conflict.
webService = createObject("webservice", webserviceURL, webserviceArgs);
javaLoader = createObject("component", "javaloader.JavaLoader").init(
loadPaths = [] // nothing
, parentClassLoader=webService.getClass().getClassLoader()
);
user = webService.GenerateUserObject();
userStatus = javaLoader.create("com.geolearning.geonext.webservices.Status");
user.setStatus(userStatus.Active);
WriteDump(var=user.getStatus(), label="SUCCESS: user.getStatus()");

Game NPC multi-action lua script design

I need to put scriptable NPC in my currect game project.
The project itself is developed in C++ language.
I will using Luabind to bind lua and c++.
I need to call NPC function when certain NPC clicked or timer to do something is activated.
Currently I stuck between 2 NPC script design.
Using a kind of npcname_action to differentiate every NPC.
This is kind of troublesome to give name to every different NPC.
I'm still thinking how to implement this in my project.
Example:
HotelBellboy12_Click() { .. }
HotelBellboy12_TimerAction() { .. }
Using name of function.
Every npc have it own lua file.
I'm thinking to load script into memory and when needed will be loaded into luaState using luaL_loadbuffer
Example:
OnClick() { .. }
OnTimerAction() { .. }
Which one is better and why?
You could use another design.
Take advantage of the fact that table keys and values can be any type.
Let's say npc is a table containing all NPC's. Its keys are NPC' names and its values are another table. This other table keys are the actions, and its values are the function for this actions.
So, if you want bob to jump when clicked on, and alice to cry after a timer, simply do :
npc.bob.click = function () jump() end
npc.alice.timer = function () cry() end
I've done something like this before and I used something similar to your #2 option. When the map loads I load a configuration Lua file containing all the NPC data; among that is the name of the script file used for the NPC.
When I need to load the NPC in the game I compile the Lua file. NPC's can use a 'model' NPC type to dictate most of the common behavior (for example a Merchant type or a Commoner type) which is specified in the NPC configuration. These model types provide all the basic functionality such as providing a trade window when clicked. The specific NPC's use functions like OnClick() to override their model and provide custom handlers.
This worked pretty well for me, although it ends up being a large volume of scripts if your game gets large.

Outlook Add-in. How to manage Items Events

I'm doing an add-in for Outlook 2007 in C++.
I need to capture the events like create, change or delete from the Outlook Items (Contact, Appointment, Tasks and Notes) but the only information/examples I've found are for Visual Basic so I don't know how to connect the event handler.
Here is some information related: http://msdn.microsoft.com/en-us/library/bb208390(v=office.12).aspx
Any help is welcome :) Thanks
Update
Sorry for taking this long to update, I've been out of town. I have some doubts/problems that you may know how to help.
In my case, I'm taking this project that was started so I'm a bit confused about all this. I have the class OutlookAddin that derives from IDTExtensibility2. I also have this other class, called AutoSync, were I'd like to do all the methods when the event fires and so. An object of this class is initialized in OutlookAddin.cpp OnStartupComplete.
According to your post MyClass should extends from IDispEventSimpleImpl<1 /*N*/, MyClass, &__uuidof(Outlook::ItemsEvents)> but which one of them? OutlookAddin or AutoSync ?
Where I should put this code also?
CComPtr<Outlook::MAPIFolder> folder;
// get the folder you're interested in
CComPtr<Outlook::_Items> items;
hr = folder->get_Items(&items);
hr = MyItemEvents::DispEventAdvise(items, &__uuidof(Outlook::ItemsEvents));
typedef IDispEventSimpleImpl<1 /*N*/, MyClass,
&__uuidof(Outlook::ItemsEvents)> MyItemEvents;
I've read the links you posted but still having these doubts...
Update 2
This is more complicated to understand than I though in a first instance.
So I have like this:
OutlookAddin.h
class OutlookAddin :
public IDTExtensibility2,
public IDispEventSimpleImpl<1, OutlookAddin, &__uuidof(Outlook::ItemEvents)>
...
BEGIN_SINK_MAP(OutlookAddin)
SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemEvents), 0xf002, OutlookAddin::OnItemChange, &OnSimpleEventInfo)
END_SINK_MAP()
...
void __stdcall OnItemChange();
'OnSimpleEventInfo' is defined like:
extern _ATL_FUNC_INFO OnSimpleEventInfo;
_ATL_FUNC_INFO OnSimpleEventInfo = {CC_STDCALL,VT_EMPTY,0};
then in OutlookAddin.cpp, OnConnection method:
CComPtr<Outlook::MAPIFolder> folder;
CComPtr<Outlook::_Items> items;
OutlookWorker::GetInstance()->GetNameSpacePtr()->GetDefaultFolder(olFolderContacts, &folder);
folder->get_Items(&items);
DispEventAdvise(items, &__uuidof(Outlook::ItemsEvents));
being 'OutlookWorker::GetInstance()->GetNameSpacePtr()' the _NameSpacePtr where all the environment is kept.
The expected behaviour here is to fire the function 'OnItemChange' from OutlookAddin class when an ContactItem is created/edited/deleted but that's not happening... I changed a little bit the structure to everything is in the main class OutlookAddin. Then on the function 'OnItemChange' I'll start the object of 'AutoSync' that I told you before.
Anyway I'm following the articles you gave me, really useful, thank you. Do you still have any other suggestion for me?
Thanks your patience.
Its been a while, but you should get these item events by advising for Folder.Items:
CComPtr<Outlook::MAPIFolder> folder;
// get the folder you're interested in
CComPtr<Outlook::_Items> items;
hr = folder->get_Items(&items);
hr = MyItemEvents::DispEventAdvise(items, &__uuidof(Outlook::ItemsEvents));
Where your class MyClass derives from:
IDispEventSimpleImpl<1 /*N*/, MyClass, &__uuidof(Outlook::ItemsEvents)>
And MyItemEvents is:
typedef IDispEventSimpleImpl<1 /*N*/, MyClass,
&__uuidof(Outlook::ItemsEvents)> MyItemEvents;
N identifies your sink here. Then there is the joy of the remaining macros to setup and the handler functions to implement - i refer you to this and this article for examples and to the dispinterface ItemsEvents that you can look up in oleview.exe.
Regarding update 1:
If you want to receive the events in AutoSync, implement the interface there - you are not required to sink the events to any specific instance. However, you know your design best :)
I'd just personally keep as much logic out of the central addin class as possible.
The registration code would go into some method of the class implementing the events then and called whenever it should start to receive events, while the typedef would be e.g. well placed in the class' declaration.
Regarding update 2:
From a quick glance it looks mostly right, but OnItemChange() takes one parameter - an IDispatch:
_ATL_FUNC_INFO AtlCallDispatch = {CC_STDCALL, VT_EMPTY, 1, {VT_DISPATCH}};

Changing the Total Number of Recent Files

I'd like the user to be able to edit the number of recent files shown in the File menu of my MFC application. I've used two very good references:
http://www.codeproject.com/KB/menus/changemru.aspx
http://www.microsoft.com/msj/0899/c/c0899.aspx
It involves deleting and recreating the CRecentFileList object stored in CWinApp::m_pRecentFileList. Unfortunately, I find that the menu is not updated properly after replacing the CRecentFileList. See code snippet below:
void CMyWinApp::SetMRUListSize( int size )
{
// size guaranteed to be between 1 and 16
delete m_pRecentFileList ;
LoadStdProfileSettings( size ) ;
}
What can I do to ensure that what is drawn into the File menu is synchronized with m_pRecentFileList after I recreate the object?
My CApp derives from CWinApp. In initInstance, you have this line:
LoadStdProfileSettings(10);
At the end of InitInstance, add this code:
m_pmf->m_pRecentFileList = m_pRecentFileList;
Here m_pmf is my MainFrame class and I created a member CMainFrame::m_pRecentFileList of type CRecentFileList which is in the MFC source file filelist.cpp. m_pRecentFileList on the right is protected and CMainFrame doesn't have access to it from outside InitInstance, but you can make a functional copy here.
At the end of CMainFrame::OnClose, force a registry update by:
m_pRecentFileList->WriteList();
// Force registry update on exit. This doesn't work without forcing.
I don't even have to rebuild m_pRecentFileList, the MRU mechanism updates it correctly. Example: 5 MRU items, the first is moved to another directory and can no longer be found. Stepping through the code in the debugger shows that the bad entry is removed from the list. For some reason, the updated list isn't saved correctly unless I force it as explained above. I originally thought the problem might have something to do with privileges (64-bit Win7), but running the app as admin didn't help.
Some of Microsoft's documentation suggest you should call CWinApp::LoadStdProfileSettings from within InitInstance. This suggests to me that it's something done once during initialisation rather than at run time.
Have you tried fully implementing the second of the two links you provided? My guess is you need to add the second part instead of the call to CWinApp::LoadStdProfileSettings:
m_pRecentFileList = new CRecentFileList(0, strSection, strEntryFormat, nCount);
if(m_pRecentFileList)
{
bReturn = TRUE;
// Reload list of MRU files from registry
m_pRecentFileList->ReadList();
}
[Edit] Apparently m_pRecentFileList points to an CRecentFileList Class . Have you tried calling CRecentFileList::UpdateMenu?
There's another CodeProject example which might help too.