How to set a custom color in C# (Visual studio)? [duplicate] - visual-studio-2017

Within the Visual Studio Designer, under the properties window you are able to select the ForeColor, BackColor etc using color picker. When you want to pick a color, a color picker comes up with the tabs 'Custom, Web, System'.
If you select custom, then you are able to add a new color to the picker, but only the bottom 2 rows are changeable, and the changes don't persist across controls. So if you add a color to the palette, when you select another control and want to change for example BackColor your previous added color is not there.
Is there a way to create and import a custom set of colors into the designer's color-picker control?
Note: This question isn't asking about VS themes, or if colors can be implemented as a class in the code-behind. I'm after a way to tailor the designer.

The editor that helps you to pick color in visual studio is ColorEditor which doesn't persists custom colors across different controls. To solve the problem, you should:
Create a custom UITypeEditor based on ColorEditor
Register the editor for type Color at visual studio startup
Here is a detailed answer including codes which I used to solve the problem.
Create CustomColorEditor
ColorEditor uses a private ColorUI class to show a private ColorPalette control. The palette uses an array of colors to show custom colors.
To create CustomColorEditor I derived from ColorEditor and using reflection, found those members and filled the array using a static array of some colors to show at first load. Then after closing the editor, I get custom colors from the editor and put them in the static array and initialize the color editor using this static array at next load. This way custom colors are shared between all instances of my CustomColorEditor.
Show CustomColorEditor instead of default ColorEditor
To show an ui type editor for all properties of a specific type, you should add an Editor attribute to the type. But since Color is not my type, how could I add Editor attribute to it?
TypeDescriptor.AddAttributes helped me to register the editor for Color type.
Where should I run the code to register the attribute? Surely at visual studio run-time!
To do so, I created a Visual Studio Package project and put the registration code at Initialize method of package. I also added ProvideAutoLoad attribute to the package class to make it auto load when I open a solution.
Then I installed the package.
Then I put the dll in GAC using gacutil.exe /i "path to dll". Instead of GAC also can put the dll in Visual Studio near devenv.exe because the visual stusio run-time will use it to show my custom color editor for all color properties.
Conclusion
After performing above tasks, I opened a new visual studio instance and in my Windows Forms project, I see my custom color editor shown for colors. The initial colors which I set displayed. Also the color editor persisted custom colors even between different forms!
I shared the codes here. You can use the idea and codes to enhance the editor. You can provide your custom colors to show in editor at start. You even can add another tab to the editor. Here is my codes:
Code for Color Editor
class CustomColorEditor : ColorEditor
{
private static Color[] Colors;
static CustomColorEditor()
{
Colors = new Color[]{
Color.Red, Color.Green, Color.Blue, Color.White,
Color.White, Color.White, Color.White, Color.White,
Color.White, Color.White, Color.White, Color.White,
Color.White, Color.White, Color.White, Color.White,
};
}
public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value)
{
var colorEditorObject = this;
Type colorUiType = typeof(ColorEditor).GetNestedType("ColorUI", BindingFlags.NonPublic);
var colorUiConstructor = colorUiType.GetConstructors()[0];
var colorUiField = typeof(ColorEditor).GetField("colorUI", BindingFlags.Instance | BindingFlags.NonPublic);
var colorUiObject = colorUiConstructor.Invoke(new[] { colorEditorObject });
colorUiField.SetValue(colorEditorObject, colorUiObject);
var palField = colorUiObject.GetType().GetField("pal", BindingFlags.Instance | BindingFlags.NonPublic);
var palObject = palField.GetValue(colorUiObject);
var palCustomColorsField = palObject.GetType().GetField("customColors", BindingFlags.Instance | BindingFlags.NonPublic);
palCustomColorsField.SetValue(palObject, Colors);
var selectedValue = base.EditValue(context, provider, value);
Colors = palCustomColorsField.GetValue(palObject) as Color[];
return selectedValue;
}
}
Code for Package
[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[Guid(GuidList.guidVSPackage1PkgString)]
[ProvideAutoLoad(Microsoft.VisualStudio.Shell.Interop.UIContextGuids80.SolutionExists)]
public sealed class VSPackage1Package : Package
{
public VSPackage1Package() { }
protected override void Initialize()
{
base.Initialize();
TypeDescriptor.AddAttributes(typeof(Color), new EditorAttribute(typeof(CustomColorEditor), typeof(UITypeEditor)));
}
}
Result
This would be the result in Visual Studio property window. Look at those Red, Green, Blue at the bottom of dialog which we added:

I know it's been quite some time...
You can use MergedDictionaries and reference a Resource Dictionary in your App.xml file.
That will put the colors you define in the palette but you would have to include the same Resource Dictionary and reference it in every App.xaml for every application you use, which, in my opinion, is good because sometimes you have to use custom colors for different applications.Custom Color Palette
Something like that

Related

Dynamic theme color at run time jetpack compose

I'm new to Jetpack Compose, so I'm struggling to implement a feature which is dynamic colors (and font, size,... but I think they are the same so I'll just focus on color) at run time from backend. I'll let the app the some default colors, and a whole default splash screen just to load the colors setting from the backend. In case the API request failed, it would use the last succeeded requested colors or just the default color.
Tutorials I found round the internet was just about changing the dark/light theme at run time, not changing a specific color in the color pack. In those tutorials, the color is defined in Colors.kt file which is not a composable or class or object, ...
I imagine the color within lightColors or darkColors would be something like this.
return lightColors(
primary = Color(android.graphics.Color.parseColor("#" + dynamicColorMap["One"])),
...
}
And when dynamicColorMap changes in the splashscreen, all screen later will have reference to the new value, but I don't know how to update its variable outside of a composable.
I thought of using DB to store the colors, but getting the data from DB is async, so it cannot be query in the default Colors.kt like var colorOne = DBManager.getColor("One"), I can run the async task in my splash screen before changing to the next screen but then the problem again is how to have a global state that my theme composable wrapper can have access to on every screen?
I just don't know where to start for these case.
Thank you for your time
EDIT:
I currently having the project structured in MVVM. For now, only one activity (MainActivity) is present, and inside that activity, the splash screen component or home screen or login screen,... are being navigated. So is it a good practice to create a viewmodel for the mainactivity screen, that can holds the color state for the theme?
Thanks #Maciej Ciemiega for the suggestion. I ended up structure my code like that.
In my MainActivity.kt I create a viewmodel for it.
val mainActivityViewModel by viewModels<MainActivityViewModel>()
MyTheme(mainActivityViewModel = mainActivityViewModel) {
initNavigationController(navController)
Surface(color = MaterialTheme.colors.background) {
if (mainActivityViewModel.appSettingsState.value.appSettings.colorsMapLight.size != 0
&& mainActivityViewModel.appSettingsState.value.appSettings.colorsMapDark.size != 0) {
navController.navigate(NavigationDestinations.homeScreen)
}
}
}
my initNavigationController function shows the splashscreen first. But it doesn't do anything. The getting app settings configuration is called in MyTheme composable via the mainActivityViewModel, and MyTheme will use the state from the viewmodel to define the theme, and the navController.navigate is based on the state as you guys can see in the if above.
I don't know if this is a good practice or not, or when my app grows it would be a mess or not, but at least it works for me. I tried with font styles too and it works like a charm.

How to implement Palette type for different platforms in QML

So at the moment I have 3 Qml types:
ThemeToUse.qml
QtObject {
property Palette palette: Palette {}
Component.onCompleted: {
if (themeContext) {
palette = themeContext.palette
}
}
}
Palette.qml
QtObject {
property color WindowsColor: "red"
}
BaseTheme.qml
QtObject {
property Palette palette: BaseTheme.Palette {}
}
BaseTheme.Palette.qml
Palette {
WindowsColor: "green" // can reimplement existing colors
property color NewColor: "black" // and add some more colors
}
And I have Theme.qml for an android app:
BaseTheme {
palette: BaseTheme.Palette {
NewColor: "blue"
readonly property color androidColor: "#010101"
}
}
Also I make the ThemeToUse in the main:
QQmlComponent qmlComponent(&engine, "path to AndroidTheme");
auto createdComponent = qmlComponent.create(context);
context->setContextProperty("themeContext", createdComponent);
And somewhere I heard that this is not the best way to make a Palette which will contain only the needed colors for different platforms.
So the question is: are there any methods to make different Palettes for different platforms, so that I can access their properties in this form: Palette.SomeColor (not the WinPalette.SomeColor and AndroidPalette.SomeColor)
Btw. I'm sorry for my english
I recommend using a QQmlFileSelector. It will allow you to add different versions of any qml file, based on platform or any other selector string that you choose.
Let's say I have a file called MyTheme.qml. And let's say, I want that file to look different if I run on Windows vs Android. My directory structure would look something like this:
qml/
MyTheme.qml
+android/
MyTheme.qml
In this case, the Windows version will be the default because I'm not specifying a special path for it. But if Qt detects that I'm running on the Android platform, whenever I request a qml file, Qt will look for it first in the +android path.
If you are using a QQmlApplicationEngine, then you don't even need to make any changes in C++. The QQmlFileSelector is already created for you.

How does the MFC PropertyGrid control work in the dialog editor in visual studio?

In the visual studio dialog editor i can add a MFC Property Grid control to the dailog. How can i customize its content, and set options like allowing the user to edit the contents of it when the program using it is running, or how i can change the contents of it using c++?
When i add something like a button or and edit control it displays on the dailog box when the program is running, while when i add a MFC Property Grid the dailog isnt even being displayed.
Here is a picture of the visual studio dialog editor and a MFC property control grid in the middle of the dailog with contents i dont know how to change.
Simple tutorial of CMFCPropertyGridCtrl:
1.Create a dialog-based MFC project, drag a CMFCPropertyGridCtrl into it, and adjust the size. Then change the ID for the control to IDC_MFCPROPERTYGRID_TEST, and use Add Varible to add a variable m_propertyGrid to the control. Change the setting of Notify to True.
Description Rows Count refers to the number of rows in the description section below.
Enable Description Area indicates whether to enable the following description function.
Enable Header indicates whether to start the header.
Mark Modified Properties indicates whether to highlight the changes.
2.Set interface
Add the following code in OnInitDialog()
HDITEM item;
item.cxy=120;
item.mask=HDI_WIDTH;
m_propertyGrid.GetHeaderCtrl().SetItem(0, new HDITEM(item));
Add content
Add the following code in OnInitDialog()
CMFCPropertyGridProperty* pProp2 = new CMFCPropertyGridProperty(
_T("choose"),
_T("select"),
_T(""));
pProp2->AddOption(_T("1"));
pProp2->AddOption(_T("2"));
pProp2->AddOption(_T("3"));
pProp2->AllowEdit(FALSE); //Editing of options is not allowed
m_propertyGrid.AddProperty(pProp2);
The three parameters passed in when calling the constructor are item name, default options and description text.
Also, you could add drop-down menu:
CMFCPropertyGridProperty* pProp2 = new CMFCPropertyGridProperty(
_T("choose"),
_T("select"),
_T(""));
pProp2->AddOption(_T("1"));
pProp2->AddOption(_T("2"));
pProp2->AddOption(_T("3"));
pProp2->AllowEdit(FALSE); //Editing of options is not allowed
m_propertyGrid.AddProperty(pProp2);
In addition, there are three similar projects:
CMFCPropertyGridColorProperty * pProp3 = new CMFCPropertyGridColorProperty(
_T("colour"), RGB(0, 111, 200));
m_propertyGrid.AddProperty(pProp3);
CMFCPropertyGridFileProperty * pProp4 = new CMFCPropertyGridFileProperty(
_T("open file"), TRUE, _T("D:\\test.txt"));
m_propertyGrid.AddProperty(pProp4);
LOGFONT font = { NULL };
CMFCPropertyGridFontProperty * pProp5 = new CMFCPropertyGridFontProperty(
_T("select font"), font);
m_propertyGrid.AddProperty(pProp5);
Finally, This is the final program running interface:

Customize visualization toolbar in PowerBi embedded editor

Is it possible to customize the visualizations toolbar of the PowerBi embedded editor? I want to hide some visual (for example all the charts, and leave only the table visuals)
Working with PBIE too.
Currently there is no legal way to customize/hide visuals pane via API or SDK.
You always can play with jQuery selectors for hiding things.
As idea just set event handler on rendered and then try something like $(".visual-types-container button").slice(0,24).each(function(elem) { $(this).remove();})
Plus handle special cases like expand/collapse pane:
$("article.visualizationPane button.toggleBtn").on("click", function() {
var parent = $("article.visualizationPane");
console.log("catch");
if(!parent.hasClass("isCollapsed"))
{
var showVisuals = ["Slicer", "Table", "Matrix"];
$("article.visualizationPane div.visual-types-container button").filter(function()
{
return -1 == showVisuals.indexOf($(this).attr("title"))
}).each(function() {
$(this).remove();
});
}
});
Everything can be broken once Microsoft released changes with new UI design.

How to setUp UiTableViewController below the battery bar

newBie here. I have added an UItableViewController into storyBoard. I use this as a setting page.
HomeVC ----> Setting VC
In code : I use the below code to bring the tableView below the battery Bar:
self.tableView.contentInset = UIEdgeInsets(top: 20,left: 0,bottom: 0,right: 0)
Problem:
How to move the TableView down below the battery bar so that I can add a button above the table in StoryBoard
Please help.
For this you should use a normal view controller and drag a table on the view controller this way you can make the table size whatever you like. This will also allow you to place buttons wherever you like.
Don't forget to assign the TableViewDataSource and TableViewDelegate to your view controller.
Good luck!
After doing some search on UiTableViewController, to use it as setting page I have to set static cell to it. This UiTableViewController will occupy the entire view.
To set the tableView below the battery icon,
use:self.tableView.contentInset = UIEdgeInsets(top: 20,left: 0,bottom: 0,right: 0)
However, No need to do so. In the first TableViewSection, you can create a few tableView cell, just leave the first cell blank which acts as a margin below the battery bar.