How does one translate the Microsoft ButtonBase.Click Event information for C++/WinRT into a prototype declaration and definition?
In Visual Studio Community 2017, version 15.9.5, I created a standard project, viz., Blank App (C++/WinRT), which has a button (myButton) as part of it. I want to learn how to add a second button. I have added the XAML code for a second button (myButton2), but thereafter I am stuck.
<Page
x:Class="X003.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:X003"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel x:Name="stackPan" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Background="LightBlue">
<Button x:Name="myButton" Click="ClickHandler">Click Me</Button>
<Button x:Name="myButton2" Click="ClickHandler2">Click Me2</Button>
</StackPanel>
</Page>
I could just copy the code from the first button that the Blank App (C++/WinRT) provided. But, if I did not have the first button as an example, I would not know how I would translate the Microsoft documentation, viz.,
// Register
event_token Click(RoutedEventHandler const& handler) const;
// Revoke with event_token
void Click(event_token const& cookie) const;
// Revoke with event_revoker
Click_revoker Click(auto_revoke_t, RoutedEventHandler const& handler) const;
into a Click handler. The first line of the Microsoft documentation, viz.,
event_token Click(RoutedEventHandler const& handler) const;
is, I take it, the format to be used in creating the handler. It does not look like the handler already in the project, viz.,
void ClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args);
I thought that it could be added to the .idl file. But, the .idl file does not have the first button in it.
The example code with Microsoft provides is for C#, even when "C++/WinRT" is selected at the top-right of the page.
The new version of C++/WinRT has a lot of documentation, almost too much. Coming from having used C#/WPF/XAML, I cannot see my way clearly to doing similar work with C++/WinRT.
Finally, the project Properties tab is of no help. In C# the events were listed and choosing one would result in a declaration and basic definition being created in the code. For C++/WinRT, when the cursor is on the control in the XAML page, the events section of the Properties page shows the name of the control, myButton or myButton2, and indicates "The document item has no code-behind file. Add a code-behind file and a class definition before adding event handlers." But, there is no code-behind file for the existing button, myButton.
How does one translate the Microsoft ButtonBase.Click Event information for C++/WinRT into a prototype declaration and definition?
Not sure what do you mean by prototype declaration and definition since given information itself is prototype.
In this page you can find more information about event handling in C++/Winrt. Link explains about handling and revoking events with delegates and gives example of Button click event handling for C++/WinRT. In short you need to have handler and register it through delegate.
// function that handles event
void MainPage::ClickHandler(IInspectable const& /* sender */, RoutedEventArgs const& /* args */)
{
Button().Content(box_value(L"Clicked"));
}
...
// register above function for event handler
Button().Click({ this, &MainPage::ClickHandler });
UPD: I tried to check regarding error The document item has no code-behind file. Add a code-behind file and a class definition before adding event handlers when user tries to access Properties and Event Handlers. I could easily reproduce this issue by creating Blank App (C++/Winrt) after installing cppwinrt extension.
I checked photo editor sample app from ms github to further down debug this problem. In this sample app I failed to load XAML design mode. First it requested me to update my Windows version to 1809, but I failed to update. So I decided to rollback to this commit id which does not require Windows 1809 update.
After this XAML design failed with Some assembly references are missing. Building to restore the NuGet cache might resolve this issue. error. Research lead me to this issue which is closed with following comment
This is currently unsupported. The XAML team is currently working on designer support, so you should see this light up in a future update to the Windows SDK.
After opening issue in MS docs github, I got following response from them and according page of MS docs was updated.
I've added the following info to the "Blank App (C++/WinRT)" subsection of this topic, since that's the project template that uses XAML as its UI.
"Visual Studio's XAML design surface support for C++/WinRT is close to parity with C#. One exception is the Events tab of the Properties window. With a C# project, you can use that tab to add event handlers; with a C++/WinRT project, that facility is not present. But see Handle events by using delegates in C++/WinRT for info on how to add event handlers to your code."
This change should be live soon. Please let me know if there's anything further I can add.
Related
I just started the GUI development, i had started on C++Builder but i switched to Visual Studio for differents reasons. But in Visual Studio, i've got a big problem :
In the GUI development interface (rc file) i can create buttons and place it, but i can't change there names. The name for all of MFC components i placed is initialize to a default name which i can't call and i can't change the property by the properties interface, i can change the Text, for change the Label of the Button, but not the name...
It's very incomfortable because by that i can't call my buttons for do anything, i have the same problem for Listboxs, so i can't modify my list because i can't call there
I just want to modify access my component by my c++ code for modifying this component
enter image description here
Thank for your help !
The MFC way of doing event handling is a bit more elaborate.
After the control is created on the form in the designer, an ID is generated ("IDC_BUTTON1" in the attached screenshot).
This is the ID that will be used for accessing this UI control from the code.
All this can be done via the designer also as shown in this article.
Basically, in the background this generated ID is put in a 'message map'
(more about message maps here).
In short 'message map' is used to specify what action needs to be performed when a certain type of action is done on the UI control by the user.
For, example if the button click is to be handled then in code:
the message map would look like:
BEGIN_MESSAGE_MAP(CSurface3DView, CView)
ON_BN_CLICKED(IDC_BUTTON1, CallMyFunction)
END_MESSAGE_MAP()
'ON_BN_CLICKED' is a predefined event macro.
The 'CallMyFunction()' function has to be declared with 'afx_msg' in the class. Besides please, have a look at data exchange mechanism as well. This know-how about data exchange will come in handy going forward.
I managed to send Toast messages but once clicked, the callback is not invoked. This is the toast-tutorial that was used.
The messages should be sent through classic Win32 and in order to do this, a shortcut needs to be created which contains the AUMID and the CLSID. This is explained in Step 5 of the tutorial, where for MSIX and WiX these id's are put in their config files. There isn't an explanation how to generate the shortcut in Win32, but can be found in another aumid-tutorial.
After following the steps provided, sending the toast works fine, but clicking it does not invoke the callback for handling the feedback.
One thing that stands out, is that the installShortcut function uses only the AUMID in the creation of the shortcut, the CLSID is only used when registering the COM Server, where the configuration for MSIX and WIX shortcuts use both.
It seems as there is the link missing that windows needs to route the feedback back into the app.
Toasts use the "ToastGeneric" binding.
Any idea why this is happening?
Just on the name alone it seems to me like you need to set the PKEY_AppUserModel_ToastActivatorCLSID property on the .lnk and not just the AUMID.
MSDN says:
Used to CoCreate an INotificationActivationCallback interface to notify about toast activations.
This page is marked as pre-release but does have a different InstallShortcut function that sets this property.
I have run the desktop-toasts sample successfully. As the code comment comments,
For the app to be activated from Action Center, it needs to provide a
COM server to be called when the notification is activated. The CLSID
of the object needs to be registered with the OS via its shortcut so
that it knows who to call later. The WiX installer adds that to the
shortcut. Be sure to install the app via the WiX installer once before
debugging!
If running the package project directly, It also works. The following picture shows What happens when I installed DesktopToastsCppWrlApp.msi generated by Wix Toolset.
I am upgrading a windows forms app. The app uses an active x control (ocx) file. We have gotten the ocx to compile and can register it. The main class in the C++ active x control project is a COleControlModule. When I go to add the control to the windows forms app like this
Me.Controls.Add(Me.ActiveXClass)
I get
Unable to cast COM object of type 'System.__ComObject' to class type
'System.Windows.Forms.Control'.
I know the active x class is a com object and I know that this COleControlModule class must not be compatible with a windows forms control. Is there anything I can do to make this work?
Any help is greatly appreciated.
This isn't working because a Runtime Callable Wrapper (RCW) is not a Windows Forms control. Only Windows Forms controls will work; to use an ActiveX control with the form, you must generate a Windows Forms wrapper for the ActiveX control. This is done with Aximp.exe, typically via adding the control to the Toolbox, as Hans suggested and then dragging an instance of the control to the form.
The steps are:
Select 'Choose Items, either from the Tools menu or by right-clicking the Tools tab
Select the COM Components tab
Select the ActiveX control either directly from the list or through the Browse button
From the Tools dialog, select the newly-added component with the mouse and drag it to the form.
A reference to the ActiveX control will be added to the project, as in this sample with the Adobe PDF reader:
<ItemGroup>
<COMReference Include="AcroPDFLib">
<Guid>{05BFD3F1-6319-4F30-B752-C7A22889BCC4}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
<COMReference Include="AxAcroPDFLib">
<Guid>{05BFD3F1-6319-4F30-B752-C7A22889BCC4}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>aximp</WrapperTool>
<Isolated>False</Isolated>
</COMReference>
</ItemGroup>
Note there are two entries, one to generate a Runtime Callable Wrapper (via tlbimp), and another to generate the AxImp wrapper (via aximp). These will be viewable in Solution View, under the project's references.
I'm currently using 3d's Max 2016 SDK via MV Studio 2012. I've created usual project with Plugin Wizard, it creates panel with text and button (and does many actions inside the code, but that is not the theme).
So, now I want to add some button to activate Windows File Dialog to choose path (folder) and name of .bin-file that will be created afterwards.
I tried to find something in the toolbox at the resource editor but have not succeed.
What should I do?
As you said, you can use directly winapi to create your dialog, but the aesthetic result of the window should differ a bit from dialog already used in 3dsMax. Autodesk has made a lot of UI controls by themselves (or patched winapi ones) and provide their access in the SDK to have something homogeneous between the application and plugins.
What you are looking for here, is the function named DoMaxSaveAsDialog and should be available in Interface8.
Interface8 Class Reference
The problem is solved de-facto. Just used pushbutton and GetSaveFileName function from windows.h header.
For details, read here:
how to save file with GetSaveFileName in win32?
My program/environment...VS2010, C++, MFC100, CWinAppEx, CMDIFrameWndEx. MFC feature pack.
I am creating and handling a CPreviewView derivative. My method treats this preview view as a normal view that the user can keep up and active. Where as the default PreviewView paints over the current view and 'takes over' the child frame.
One thing I can't figure out is how to gain control over the ON_UPDATE_COMMAND_UI message maps that should be directed to all CDocuments. When a CPreviewView is created it somehow disables all the command handlers to CDocuments. The command handlers to CViews are still up and working.
All Documents open in my MDI app don't receive their ON_UPDATE_COMMAND_UI messages. I can move these message handlers out to the View, or Frame but there are too many to do this efficiently.
Does anyone know where in the CPreviewView class turns off document handlers?
First of all, MFC is not a "locked" framework. Its complete source resides on your own PC in the following folder: "your Visual Studio folder"\VC\atlmfc\src\mfc\ (on my PC it is: c:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\src\mfc) The source for CPreviewView is in viewprev.cpp file. I just opened the file and in the DoPrintPreview they are calling this:
pParent->OnSetPreviewMode(TRUE, pState); // Take over Frame Window
According to MSDN this method:
The default implementation disables all standard toolbars and hides the main menu and the main client window. This turns MDI frame windows into temporary SDI frame windows.
I have opened the file called winfrm.cpp and checked that this method is doing, and it does disable all the menu. Obviously, no Update messages will be sent to documents while preview mode is on.
The MSDN article at the hyperlink above says that you need to override the OnSetPreviewMode method for your frame to:
customize the hiding and showing of control bars and other frame window parts during print preview. Call the base class implementation from within the overridden version.
This should not be a problem.