winforms userControl inside MFC with no Clr - winforms

I have an MFC application that uses some specific files with CLR but not the whole project.
The challenge is I want to embed a WinForms user control inside the MFC project without the whole project compiled with CLR.
As mentioned before, in one of the existing managed files I created a method that does the exchange with the ctrl like so:
#include <afxwin.h>
#include <afxwinforms.h>
#include "Managedfile.h"
void CWinformsUtil::CreateFullListeUc(CDataExchange* pDX, int Idc)
{
CWinFormsControl<MainuserControlLib::UserControl2> m_ctrl1;
DDX_ManagedControl(pDX, Idc, m_ctrl1);
}
And I am calling this method inside the DoDataExchange method in the MFC app source:
void CMFCApplication1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
CWinformsUtil::CreateFullListeUc(pDX, IDC_STATIC1);
}
But the problem with this approach is that it does not display the WinForms user control.

In order to acheive this what i've did was to compile the view.cpp file in wich i want to display the user control in clr,then included <afxwinforms.h> in it .Also in the header file i need to import that library
but it should only be visile to managed code by simply making a condition :
//view.h
#ifdef _MANAGED
#include <afxwinforms.h>
#endif
and for declaring the control in the header file we need also the same approach:
//view.h
#ifdef _MANAGED
CWinFormsControl<MainuserControlLib::UserControl2> m_ctrl1;
#endif

Related

How to combine Swift and C code in a static library

I am trying to create a static library that contains Swift and C code, and exposes only a Swift interface. So the C code side should ideally not be exposed to the outside world. I can't seem to figure out the right way to do this without causing warnings or errors.
For the sake of simplification, I tried setting up a minimal Swift+C static library with these files:
Test.swift
class Test {
func test() -> CInt {
return testFromC()
}
}
Test.c
#include "Test.h"
int testFromC(void) {
return 0xdeadbeef;
}
Test.h
int testFromC(void);
What I want is a static library that exposes the Swift class Test, but not the C function testFromC(). I can live with it being exposed if there is no alternative, though.
What I have tried is:
Add a bridging header. This almost works, but a) lots of people say this is not supported or recommended, b) it exposes testFromC() to the importer of the module, and c) under some circumstances it throws warnings about implicitly importing the bridging header (which is true, but what I want is specifically to NOT do that).
Add a modulemap. I can't figure out how to do this. No examples online seem to work for me, and if anyone knows how to do this correctly, I would love to see an example for these three files.
Add a private modulemap - I gather this is what I want if I want to avoid exposing the C functions but I had even less success with this.
Is anyone able to put together the exact steps to make this trivial example build?
You can indeed create a private module map so that the C symbols are not exported, see https://clang.llvm.org/docs/Modules.html#private-module-map-files.
The bridging header would not work because you want to create a framework and not an application.
There are certainly several ways to set up the project, one of which would be: create a project with the corresponding module map settings in XCode.
The .modulemap file could look something like this:
framework module SwiftOnlyAPI {
umbrella header "SwiftOnlyAPI.h"
export *
module * { export * }
}
framework module SwiftOnlyAPI_Private {
header "Test.h"
}
Your Test.swift would rather look something like this:
import SwiftOnlyAPI_Private
public class Test {
public init() {
//perform some initializations
}
public func test() -> CInt {
return testFromC()
}
}
Please note a few small changes: the import of SwiftOnlyAPI_Private, this is necessary for the C functions that are not exported, but of course are called locally within the framework. Classes and exported methods must be public to be accessible from outside the framework.
Instructions
<File/New Project...> choose Framework, choose Language Swift name it SwiftOnlyAPI
add you files (.c,.h,.swift) to the SwiftOnlyAPI folder
select Test.h in the project navigator and switch the target membership in the inspector from Project to Private
choose SwiftOnlyAPI in the project navigator, select the SwiftOnlyAPI target
now click on Build Settings and for Mach-O Type select: Static Library
still in Build Settings: for Module Map File enter: SwiftOnlyAPI/SwiftOnlyAPI.modulemap
select the folder SwiftOnlyAPI in the SwiftOnlyAPI project, choose New File... from the context menu and, choose Empty template from the Other section and name it SwiftOnlyAPI.modulemap (uncheck target membership)
add the modulemap content shown above
A test produces the desired result, just as shown for the alternative solution for multiple targets below.
Static Library
Frameworks are really just either dynamic or static libraries (depending on the setting) with additional bundled files. Convenient for the framework users.
You can test this yourself with the file command:
Alternative
If you want to have the C part separate (e.g. for other consumers), you can also split it into two subprojects in an Xcode workspace, one for a static C lib and one for a static Swift-based framework:
create a XCode workspace <File/New Workspace...>, e.g. name it SwiftCWorkspace
<File/New Project...> choose Library, choose under Framework None (Plain C/C++ Library), name it MyCLib and choose type Static
in the dialog choose for Add to and Group: SwiftCWorkspace
select the MyCLib node in project navigator, choose New File... from the context menu and choose C file template, name it Test
replace the content with your Test.c and Test.h content
<File/New Project...> choose Framework, choose Language Swift name it SwiftOnlyAPI
in the dialog choose for Add to and Group: SwiftCWorkspace
select the folder SwiftOnlyAPI in the SwiftOnlyAPI project, choose New File... from the context menu and, choose Swift template and replace it with your ccontent
choose SwiftOnlyAPI in the project navigator, select the SwiftOnlyAPI target
now click on Build Settings and for Mach-O Type select: Static Library
still in Build Settings: for Module Map File enter: SwiftOnlyAPI/SwiftOnlyAPI.modulemap
now click on General and in the Frameworks and Library section add libMyCLib.a
select the folder SwiftOnlyAPI in the SwiftOnlyAPI project, choose New Group... from the context menu and name it MyCLib
drag & drop Test.h from MyCLib project to the MyCLib folder in SwiftOnlyAPI, uncheck Copy items if needed
with the newly linked file Test.h selected switch the target membership in the inspector from Project to Private
select the folder SwiftOnlyAPI in the SwiftOnlyAPI project, choose New File... from the context menu and, choose Empty template from the Other section and name it SwiftOnlyAPI.modulemap (uncheck target membership)
add the modulemap content shown above
Notes
If Xcode displays error messages even though you have set everything up correctly, it is occasionally necessary to exit Xcode after the project setup tasks, delete the ~/Library/Developer/Xcode/DerivedData folder, and then restart the build.
Test
import SwiftOnlyAPI
...
let result = SwiftOnlyAPI.Test()
print(result.test())
You can test this in a separate application using the SwiftOnlyAPI framework: the correct result will be output.
Also the C function testFromC is private and not externally accessible as desired, see screenshot:

How to handle Solutions, Projects and their contents in a VisualStudio extension

In short:
I'm new to VisualStudio Extensibility and my goal is to create an extension with a ToolWindow (which already works) showing different views for each context of a VisualStudio solution, i. e. a view for the solution, a view for a project etc.. The window should be opened by clicking on a context menu entry in the context menus of the Solution Explorer, Class View, Object Browser and (ideally) any other window showing contents like projects, namespaces, classes etc..
After searching I found a lot of information, but for some points I couldn't find very helpful information. How do I ...
... create a context menu item for the VisualStudio views?
... get the currently open solution as an instance in code?
... get the projects of the solution and their contens as instances in code?
... add/remove items to/from a solution/project/class/... in code?
... react to selection changes in the Solution Explorer?
What I've done, so far:
I read the docs for Starting to Develop Visual Studio Extensions and downloaded the VSSDK-Extensibility-Samples. Especially the WPF_Toolwindow example was interesting for my purposes, so I built and ran it, which was successful, so far. Another interesting sample would have been the WPFDesigner_XML, but it always throws a NullReferenceException, so I decided to stick with the former ToolWindow, which is completely fine, for now.
Furtermore, I tried to understand the example by having a close look at each file in the project, running it in the debugger and analyzing what happened. I'm confident I understood it, but am also open for corrections of my possibly misguided thoughts following.
Now, I have created a new project, based on the WPF_Toolwindow sample, renamed and adapted to my needs (basically, I created new GUIDs, renamed the namespaces and removed things I won't use). This extension still works in the debugger. I even uninstalled everything from the experimental instance and debugged the extension from scratch.
What I try to achieve:
Have the ToolWindow load a specific view/viewmodel, when the selection changes in the Solution Explorer (or any other VisualStudio view). Alternatively, there should be a context menu item for every node's context menu in the Solution Explorer tree (or any other VisualStudio view).
Get the currently open solution, the containing projects and basically everything from the Solution Explorer's content as instances processable in my viewmodel. I need to properly add/remove
classes/structs/enums to/from
a folder in a project
a namespace
properties/fields to/from a class/struct
Generate code based on information of the solution and add the file properly to a project.
Does anyone know of examples for something like this or can anyone give me some hints, where I can find further information? Any help would be appreciated. Thanks in advance.
(1) The items already have a context menu and I want to add a new command to this menu.
if you want to add a sub menu to the context menu, the following link provide a complete sample
https://github.com/visualstudioextensibility/VSX-Samples/tree/master/CommandSubmenu
(3) Yes, basically adding a file to a project without manually manipulating the project file would be nice.
You can add the file to project via Project.ProjectItems.AddFromFile, and the following provide a sample for your reference.
https://www.mztools.com/Articles/2014/MZ2014009.aspx
Update:
I select a project and a similar event is fired. Are there such events I can subscribe to?
You could use IVsMonitorSelection to implement. here is the code which retrieve related project path for your reference.
IntPtr hierarchyPointer, selectionContainerPointer;
Object selectedObject = null;
IVsMultiItemSelect multiItemSelect;
uint projectItemId;
IVsMonitorSelection monitorSelection =
(IVsMonitorSelection)Package.GetGlobalService(
typeof(SVsShellMonitorSelection));
monitorSelection.GetCurrentSelection(out hierarchyPointer,
out projectItemId,
out multiItemSelect,
out selectionContainerPointer);
IVsHierarchy selectedHierarchy = Marshal.GetTypedObjectForIUnknown(
hierarchyPointer,
typeof(IVsHierarchy)) as IVsHierarchy;
if (selectedHierarchy != null)
{
ErrorHandler.ThrowOnFailure(selectedHierarchy.GetProperty(
projectItemId,
(int)__VSHPROPID.VSHPROPID_ExtObject,
out selectedObject));
}
Project selectedProject = selectedObject as Project;
string projectPath = selectedProject.FullName;
For more information about the usage, please refer to:
https://www.mztools.com/articles/2007/mz2007024.aspx

How to open a text file from CLI using a running instance of a GTK text editor written in C?

I have a text editor written in C using gtk+-3.x and gtksourceview3. I would like to expand the functionality to include the ability to open a text file from the command line and add the text in this file to a new buffer in the previously opened editor.
So the question is, how do I access this text? I can add it to a buffer,scrollwin... that isn't the problem. Thanks.
I'm assuming your problem is what's mentioned in the title: getting an already running instance of a GTK app to do something from the command line.
GtkApplication and it's base class GApplication will give you the tools you need: It allows you to define actions that the new instance can invoke on the original instance (using D-Bus but that's an implementation detail). For your use case take a look at the already defined "open" action in GApplication (see example).
If you are using a an old version of GTK+ that doesn't have GtkApplication, you can use libunique instead -- the API is roughly the same.

MissingManifestResourceException for EmbeddedResouce in Silverlight

I write Silverlight games using XNA-based Silverlight engines. I have a previous game where I have files (MP3s and text files) with Build Action set to Embedded Resource, and no *.resx file to be seen in my solution.
The game runs fine; you can see the production version here.
On the other hand, my current project doesn't allow this. When I try to make files Embedded Resources, I get a MissingManifestResourceException thrown in my constructor of the main UserControl instance that starts my app. The error message is:
Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "DeenGames.Colosseum.Content.Audio.2.mp3.resources" was correctly embedded or linked into assembly "DeenGames.Colosseum" at compile time, or that all the satellite assemblies required are loadable and fully signed.
I'm very, very, very perplexed. Setting any item's Build Action to Embedded Resource, whether MP3, text, or image, causes this exception.
How the heck do I fix (or debug) this? I'm 99% sure I do not need a .resx file, because my previous projects don't have one.
There's this lovely MSDN page which assures the world that:
In particular, Silverlight embedded resources must always use the
Resource build action, and not the Embedded Resource build action,
which uses a format that Silverlight cannot recognize.
But there's a well-known solution using Assembly.GetExecutingAssembly().GetManifestResourceNames(). In my case, it doesn't show me the resource if it's just a Resource; if it's an Embedded Resource, I can see the file name with dot-delimited namespace (as expected).
Download and see for yourself a very simple working example here. It has two embedded files (.2dg and .map) and compiles/runs without any exceptions OR resx file.
You can also download a broken example here. Replace FlatRedBall.dll with RadiantWrench.dll and watch the working example break. (Use ScreenController.ShowScreen and remove all FRB-referenced code.)
Embedded Resource is a WinForms technology that is depreciated in the Silverlight runtime. Instead, a build action of Resource or Content should be used instead.
When you set an item to Embedded Resource, Silverlight expects this to be a .resx file because this is what happens inside the .csproj or .vbproj file when you create a .resx and add resources to it (the file is marked as Embedded Resource for MSBuild and its resources are simply a None inside of an <ItemGroup/> that are discovered by the ResXGenerator at runtime based off the relative URI folder of "Resources"). If it isn't, it removes it or sets it as Content. You can examine Microsoft.Silverlight.Common.targets (usually in your C:\Program Files (x86)\MSBuild\Microsoft\Silverlight\v4.0 folder) to see how it changes items marked as Embedded Resource - setting to content, setting to none or setting to a .resx file.
If you're looking to just query what resources you have in the project, you could try this somewhat cumbersome approach: Enumerating embedded resources
UPDATE: In looking at your project, this is not really using an Embedded Resource the way WinForms uses this Build Action type or even .resx, per say. It uses a function from the ToolsSilverlight.dll called EmbeddedResourceFileReader.ReadFile. The code for that is:
private static string ReadFile(string fileName, Assembly currentAssembly)
{
string text = EmbeddedResourceHelper.CheckAndSanitizePath(fileName);
string result = "";
using (Stream manifestResourceStream = currentAssembly.GetManifestResourceStream(text))
{
if (manifestResourceStream == null)
{
throw new ArgumentException("Couldn't open " + fileName + ". Make sure the file exists in that directory, and has Build Action set to Embedded Resource.");
}
using (StreamReader streamReader = new StreamReader(manifestResourceStream))
{
result = streamReader.ReadToEnd();
}
}
return result;
}
Your .csproject file lists your files as:
<ItemGroup>
<EmbeddedResource Include="Content\Qadar.2dg" />
<EmbeddedResource Include="Content\Maps\main.map" />
<None Include="Properties\AppManifest.xml" />
</ItemGroup>
All this does is embed, as mentioned with the Microsoft.Silverlight.Common.targets above, your files as common Resources (at a top level, not with the list of other actual resouces) and finds a way to read them. You can decompile your DLL with ILSpy to exam that these are indeed now common Resources under the Resources folder.
So how can you do this in your new project? Replicate the exact method you did in your first one - add ToolsSilverlight.dll, list your items as Embedded Resource, and call them using EmbeddedResourceFileReader.ReadFile. You may also want to ensure your .csproj file <ItemGroup/> structure is similar to original one. Not sure if <None Include="Properties\AppManifest.xml"/> is needed by EmbeddedResourceFileReader, but it may be.

Change Default Winform Icon Across Entire App

Can I change the default icon used on a Winform?
Most of my forms have their icon property set to a custom icon. For the few forms that slip through the cracks, I don't want the generic "hey look, he made this in visual studio" icon.
One solution is to tediously check every one of my forms to make sure they either have a custom icon set or have ShowIcon set to False.
Another solution is to have every one of my forms inherit from a base class that sets a custom icon in the constructor.
Aside from those solutions, what other options do I have?
EDIT:
I was hoping there would be a way to replace the source of the stock icon with my own. Is it in a resource file somewhere? Or is it embedded in a .NET dll that I can't (or really, really shouldn't) modify?
BOUNTY EDIT:
Is there a way to accomplish this without editing or writing a single line of code? I don't care how impractical, complicated, waste-of-time the solution is... I just want to know if it's possible. I need to satisfy my curiosity.
The default icon is embedded in the winforms dll - looking at reflector (DefaultIcon) it is:
defaultIcon = new Icon(typeof(Form), "wfc.ico");
There is no magic in there that checks another common location, so you can't do it without changing code.
You could always embrace the forces of darkness with field-based reflection? Note: this is hacky and brittle. On your own head! But it works:
[STAThread]
static void Main() {
// pure evil
typeof(Form).GetField("defaultIcon",
BindingFlags.NonPublic | BindingFlags.Static)
.SetValue(null, SystemIcons.Shield);
// all forms now default to a shield
using (Form form = new Form()) {
Application.Run(form);
}
}
To do it properly; two common options;
a base Form class which has the icon set
a factory Form method - perhaps something like:
code:
public static T CreateForm<T>() where T : Form, new() {
T frm = new T();
frm.Icon = ...
// any other common code
return frm;
}
Then instead of:
using(var frm = new MySpecificForm()) {
// common init code
}
Something like:
using(var frm = Utils.CreateForm<MySpecificForm>()) {
}
Of course - that isn't much prettier! Another option might be a C# 3.0 extension method, perhaps as a fluent API:
public static T CommonInit<T>(this T form) where T : Form {
if(form != null) {
form.Icon = ...
//etc
}
return form;
}
and
using(var frm = new MySpecificForm().CommonInit()) {
// ready to use
}
This is then just a .CommonInit() away from your existing code.
The base class option is the one that we use.
If you are looking for an alternative (not necessarily good ones), you could:
1. Use IOC to instantiate all of your forms and modify the IOC container to set the application icon.
2. Use AOP to insert code into all of the forms that sets the application icon.
Personally, I'd just use the base class...
My useful answer:
No
Would be a nice feature for microsoft to implement though, since most apps use the same icon across the entire application.
If you want to update all the icons by another one, you can build a small app that edits all the *.Designer.vb files (in vb.net) and adding the folowing line to InitializeComponent:
Me.Icon = New System.Drawing.Icon("C:\PathTo\icon.ico")
Hope it helps.
If all your forms are in just one project then you can take the dll of the project and use reflection to get every type in the dll. If the type derives from Form you can set the type's Icon property to whatever you want. I am not sure what the performance overhead will be if the project is very big.

Resources