VS: Add Windows Forms Support
Add support to maintain designer functionality for Visual Studio C++ Windows Forms projects. Also add a test project showing how to use the CMakeLists.txt file and, when successfully configured, will allow use of the designer for the included form.
This commit is contained in:
parent
c80594ba12
commit
79ec7868d0
|
@ -98,6 +98,18 @@ void cmGeneratorTarget::ClassifySources()
|
||||||
this->IDLSources.push_back(sf);
|
this->IDLSources.push_back(sf);
|
||||||
if(isObjLib) { badObjLib.push_back(sf); }
|
if(isObjLib) { badObjLib.push_back(sf); }
|
||||||
}
|
}
|
||||||
|
else if(ext == "resx")
|
||||||
|
{
|
||||||
|
// Build and save the name of the corresponding .h file
|
||||||
|
// This relationship will be used later when building the project files.
|
||||||
|
// Both names would have been auto generated from Visual Studio
|
||||||
|
// where the user supplied the file name and Visual Studio
|
||||||
|
// appended the suffix.
|
||||||
|
std::string resx = sf->GetFullPath();
|
||||||
|
std::string hFileName = resx.substr(0, resx.find_last_of(".")) + ".h";
|
||||||
|
this->ExpectedResxHeaders.insert(hFileName);
|
||||||
|
this->ResxSources.push_back(sf);
|
||||||
|
}
|
||||||
else if(header.find(sf->GetFullPath().c_str()))
|
else if(header.find(sf->GetFullPath().c_str()))
|
||||||
{
|
{
|
||||||
this->HeaderSources.push_back(sf);
|
this->HeaderSources.push_back(sf);
|
||||||
|
|
|
@ -44,11 +44,15 @@ public:
|
||||||
std::vector<cmSourceFile*> ObjectSources;
|
std::vector<cmSourceFile*> ObjectSources;
|
||||||
std::vector<cmSourceFile*> ExternalObjects;
|
std::vector<cmSourceFile*> ExternalObjects;
|
||||||
std::vector<cmSourceFile*> IDLSources;
|
std::vector<cmSourceFile*> IDLSources;
|
||||||
|
std::vector<cmSourceFile*> ResxSources;
|
||||||
|
|
||||||
std::string ModuleDefinitionFile;
|
std::string ModuleDefinitionFile;
|
||||||
|
|
||||||
std::map<cmSourceFile const*, std::string> Objects;
|
std::map<cmSourceFile const*, std::string> Objects;
|
||||||
std::set<cmSourceFile const*> ExplicitObjectName;
|
std::set<cmSourceFile const*> ExplicitObjectName;
|
||||||
|
|
||||||
|
std::set<std::string> ExpectedResxHeaders;
|
||||||
|
|
||||||
/** Full path with trailing slash to the top-level directory
|
/** Full path with trailing slash to the top-level directory
|
||||||
holding object files for this target. Includes the build
|
holding object files for this target. Includes the build
|
||||||
time config name placeholder if needed for the generator. */
|
time config name placeholder if needed for the generator. */
|
||||||
|
|
|
@ -291,6 +291,7 @@ void cmVisualStudio10TargetGenerator::Generate()
|
||||||
this->WriteCustomCommands();
|
this->WriteCustomCommands();
|
||||||
this->WriteAllSources();
|
this->WriteAllSources();
|
||||||
this->WriteDotNetReferences();
|
this->WriteDotNetReferences();
|
||||||
|
|
||||||
this->WriteWinRTReferences();
|
this->WriteWinRTReferences();
|
||||||
this->WriteProjectReferences();
|
this->WriteProjectReferences();
|
||||||
this->WriteString(
|
this->WriteString(
|
||||||
|
@ -455,6 +456,12 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
|
||||||
this->WriteString("<WindowsAppContainer>true"
|
this->WriteString("<WindowsAppContainer>true"
|
||||||
"</WindowsAppContainer>\n", 2);
|
"</WindowsAppContainer>\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!this->GeneratorTarget->ResxSources.empty())
|
||||||
|
{
|
||||||
|
this->WriteString("<CLRSupport>true</CLRSupport>\n", 2);
|
||||||
|
}
|
||||||
|
|
||||||
this->WriteString("</PropertyGroup>\n", 1);
|
this->WriteString("</PropertyGroup>\n", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,6 +654,23 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
|
||||||
this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
|
this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<cmSourceFile*> resxObjs = this->GeneratorTarget->ResxSources;
|
||||||
|
if(!resxObjs.empty())
|
||||||
|
{
|
||||||
|
this->WriteString("<ItemGroup>\n", 1);
|
||||||
|
for(std::vector<cmSourceFile*>::iterator oi = resxObjs.begin();
|
||||||
|
oi != resxObjs.end(); ++oi)
|
||||||
|
{
|
||||||
|
std::string obj = (*oi)->GetFullPath();
|
||||||
|
this->WriteString("<EmbeddedResource Include=\"", 2);
|
||||||
|
this->ConvertToWindowsSlash(obj);
|
||||||
|
(*this->BuildFileStream ) << obj << "\">\n";
|
||||||
|
this->WriteString("<Filter>Resource Files</Filter>\n", 3);
|
||||||
|
this->WriteString("</EmbeddedResource>\n", 2);
|
||||||
|
}
|
||||||
|
this->WriteString("</ItemGroup>\n", 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Add object library contents as external objects.
|
// Add object library contents as external objects.
|
||||||
std::vector<std::string> objs;
|
std::vector<std::string> objs;
|
||||||
this->GeneratorTarget->UseObjectLibraries(objs);
|
this->GeneratorTarget->UseObjectLibraries(objs);
|
||||||
|
@ -701,6 +725,23 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
|
||||||
<< "</UniqueIdentifier>\n";
|
<< "</UniqueIdentifier>\n";
|
||||||
this->WriteString("</Filter>\n", 2);
|
this->WriteString("</Filter>\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!this->GeneratorTarget->ResxSources.empty())
|
||||||
|
{
|
||||||
|
this->WriteString("<Filter Include=\"Resource Files\">\n", 2);
|
||||||
|
std::string guidName = "SG_Filter_Resource Files";
|
||||||
|
this->GlobalGenerator->CreateGUID(guidName.c_str());
|
||||||
|
this->WriteString("<UniqueIdentifier>", 3);
|
||||||
|
std::string guid =
|
||||||
|
this->GlobalGenerator->GetGUID(guidName.c_str());
|
||||||
|
(*this->BuildFileStream) << "{" << guid << "}"
|
||||||
|
<< "</UniqueIdentifier>\n";
|
||||||
|
this->WriteString("<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;", 3);
|
||||||
|
(*this->BuildFileStream) << "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;";
|
||||||
|
(*this->BuildFileStream) << "mfcribbon-ms</Extensions>\n";
|
||||||
|
this->WriteString("</Filter>\n", 2);
|
||||||
|
}
|
||||||
|
|
||||||
this->WriteString("</ItemGroup>\n", 1);
|
this->WriteString("</ItemGroup>\n", 1);
|
||||||
this->WriteString("</Project>\n", 0);
|
this->WriteString("</Project>\n", 0);
|
||||||
// restore stream pointer
|
// restore stream pointer
|
||||||
|
@ -832,8 +873,20 @@ void cmVisualStudio10TargetGenerator::WriteSource(
|
||||||
}
|
}
|
||||||
this->ConvertToWindowsSlash(sourceFile);
|
this->ConvertToWindowsSlash(sourceFile);
|
||||||
this->WriteString("<", 2);
|
this->WriteString("<", 2);
|
||||||
(*this->BuildFileStream ) << tool <<
|
(*this->BuildFileStream ) << tool << " Include=\"" << sourceFile << "\"";
|
||||||
" Include=\"" << sourceFile << "\"" << (end? end : " />\n");
|
|
||||||
|
if(sf->GetExtension() == "h" &&
|
||||||
|
this->IsResxHeader(sf->GetFullPath()))
|
||||||
|
{
|
||||||
|
(*this->BuildFileStream ) << ">\n";
|
||||||
|
this->WriteString("<FileType>CppForm</FileType>\n", 3);
|
||||||
|
this->WriteString("</ClInclude>\n", 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*this->BuildFileStream ) << (end? end : " />\n");
|
||||||
|
}
|
||||||
|
|
||||||
ToolSource toolSource = {sf, forceRelative};
|
ToolSource toolSource = {sf, forceRelative};
|
||||||
this->Tools[tool].push_back(toolSource);
|
this->Tools[tool].push_back(toolSource);
|
||||||
}
|
}
|
||||||
|
@ -1718,3 +1771,12 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
|
||||||
}
|
}
|
||||||
this->WriteString("</ItemGroup>\n", 1);
|
this->WriteString("</ItemGroup>\n", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cmVisualStudio10TargetGenerator::
|
||||||
|
IsResxHeader(const std::string& headerFile)
|
||||||
|
{
|
||||||
|
std::set<std::string>::iterator it =
|
||||||
|
this->GeneratorTarget->ExpectedResxHeaders.find(headerFile);
|
||||||
|
|
||||||
|
return it != this->GeneratorTarget->ExpectedResxHeaders.end();
|
||||||
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ private:
|
||||||
void WriteWinRTReferences();
|
void WriteWinRTReferences();
|
||||||
void WritePathAndIncrementalLinkOptions();
|
void WritePathAndIncrementalLinkOptions();
|
||||||
void WriteItemDefinitionGroups();
|
void WriteItemDefinitionGroups();
|
||||||
|
|
||||||
bool ComputeClOptions();
|
bool ComputeClOptions();
|
||||||
bool ComputeClOptions(std::string const& configName);
|
bool ComputeClOptions(std::string const& configName);
|
||||||
void WriteClOptions(std::string const& config,
|
void WriteClOptions(std::string const& config,
|
||||||
|
@ -91,7 +92,7 @@ private:
|
||||||
std::vector<cmSourceGroup>& );
|
std::vector<cmSourceGroup>& );
|
||||||
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
|
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
|
||||||
const std::vector<cmSourceGroup>& allGroups);
|
const std::vector<cmSourceGroup>& allGroups);
|
||||||
|
bool IsResxHeader(const std::string& headerFile);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef cmVisualStudioGeneratorOptions Options;
|
typedef cmVisualStudioGeneratorOptions Options;
|
||||||
|
|
|
@ -1448,6 +1448,11 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
|
||||||
ADD_TEST_MACRO(SBCS SBCS)
|
ADD_TEST_MACRO(SBCS SBCS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT "${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [6789]( |$)"
|
||||||
|
AND NOT CMAKE_TEST_GENERATOR_TOOLSET)
|
||||||
|
ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_test(VSExternalInclude ${CMAKE_CTEST_COMMAND}
|
add_test(VSExternalInclude ${CMAKE_CTEST_COMMAND}
|
||||||
--build-and-test
|
--build-and-test
|
||||||
"${CMake_SOURCE_DIR}/Tests/VSExternalInclude"
|
"${CMake_SOURCE_DIR}/Tests/VSExternalInclude"
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#
|
||||||
|
# Example CMakeLists.txt file to demonstrate how to make a designable Windows Forms project with CMake.
|
||||||
|
#
|
||||||
|
# Code modifications and example by John Farrier, john.farrier@helleboreconsulting.com
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8.10)
|
||||||
|
|
||||||
|
# Project Name
|
||||||
|
project(VSWindowsFormsResx CXX)
|
||||||
|
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
|
||||||
|
# Note: The designable form is assumed to have a .h extension as is default in Visual Studio.
|
||||||
|
# Node: The designable form is assumed to have a .resx file with the same name and path (save extension) as is default in Visual Studio
|
||||||
|
|
||||||
|
set(TARGET_H
|
||||||
|
WindowsFormsResx/MyForm.h
|
||||||
|
WindowsFormsResx/Header.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(TARGET_SRC
|
||||||
|
WindowsFormsResx/MyForm.cpp
|
||||||
|
WindowsFormsResx/Source.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(TARGET_RESX
|
||||||
|
WindowsFormsResx/MyForm.resx
|
||||||
|
)
|
||||||
|
|
||||||
|
set(TARGET_LIBRARIES ${SYSLIBS})
|
||||||
|
add_executable(${PROJECT_NAME} ${TARGET_SRC} ${TARGET_H} ${TARGET_RESX})
|
||||||
|
|
||||||
|
# Note: The property VS_GLOBAL_KEYWORD must be set.
|
||||||
|
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_KEYWORD "ManagedCProj")
|
||||||
|
|
||||||
|
# Note: The property VS_DOTNET_REFERENCES must be set.
|
||||||
|
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DOTNET_REFERENCES "System" "System.Data" "System.Drawing" "System.Windows.Forms" "System.Xml")
|
||||||
|
|
||||||
|
# Note: Modification of compiler flags is required for CLR compatibility now that we are using .resx files.
|
||||||
|
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||||
|
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
|
@ -0,0 +1 @@
|
||||||
|
#include "MyForm.h"
|
|
@ -0,0 +1,78 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Farrier {
|
||||||
|
|
||||||
|
using namespace System;
|
||||||
|
using namespace System::ComponentModel;
|
||||||
|
using namespace System::Collections;
|
||||||
|
using namespace System::Windows::Forms;
|
||||||
|
using namespace System::Data;
|
||||||
|
using namespace System::Drawing;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Summary for MyForm
|
||||||
|
/// </summary>
|
||||||
|
public ref class MyForm : public System::Windows::Forms::Form
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyForm(void)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
//
|
||||||
|
//TODO: Add the constructor code here
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
~MyForm()
|
||||||
|
{
|
||||||
|
if (components)
|
||||||
|
{
|
||||||
|
delete components;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private: System::Windows::Forms::Button^ button1;
|
||||||
|
protected:
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
System::ComponentModel::Container ^components;
|
||||||
|
|
||||||
|
#pragma region Windows Form Designer generated code
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
void InitializeComponent(void)
|
||||||
|
{
|
||||||
|
this->button1 = (gcnew System::Windows::Forms::Button());
|
||||||
|
this->SuspendLayout();
|
||||||
|
//
|
||||||
|
// button1
|
||||||
|
//
|
||||||
|
this->button1->Location = System::Drawing::Point(13, 13);
|
||||||
|
this->button1->Name = L"button1";
|
||||||
|
this->button1->Size = System::Drawing::Size(75, 23);
|
||||||
|
this->button1->TabIndex = 0;
|
||||||
|
this->button1->Text = L"button1";
|
||||||
|
this->button1->UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// MyForm
|
||||||
|
//
|
||||||
|
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
|
||||||
|
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
|
||||||
|
this->ClientSize = System::Drawing::Size(284, 261);
|
||||||
|
this->Controls->Add(this->button1);
|
||||||
|
this->Name = L"MyForm";
|
||||||
|
this->Text = L"MyForm";
|
||||||
|
this->ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
#pragma endregion
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
|
@ -0,0 +1,4 @@
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue