CSS styling in GTKSharp - c#

I'm converting a C/GTK+ GUI application to C# using GTKSharp in VS2017. I've installed this package https://www.nuget.org/packages/GtkSharp/3.1.3 via NuGet.
Here's how I load up the CSS (the application uses a Glade file to define the interface):
static void Main(string[] args)
{
new Program(args);
}
public Program(string[] args)
{
Application.Init();
builder = new Builder();
Gtk.CssProvider provider = new CssProvider();
builder.AddFromFile("interface.glade");
provider.LoadFromPath("style.css");
builder.Autoconnect(this);
Gtk.Window window = (Gtk.Window)builder.GetObject("start");
Gtk.StyleContext.AddProviderForScreen(Gdk.Screen.Default, provider, 800); // couldn't find the equivalent to GTK_STYLE_PROVIDER_PRIORITY_USER so I set the priority to a random number
window.Show();
Application.Run();
}
The selector names seem to be different from GTK+. For example,
window {
...
}
works in C/GTK+ but not in C#, whereas
GtkWindow {
...
}
works in C# but not in C/GTK+. Then there are a few widgets I can't seem to style at all. For example,
button {
...
}
works in GTK+ but
GtkButton {
...
}
does not work in C#. I couldn't find any documentation regarding how GTK# handles CSS styling so I thought it'd be the same as GTK+. Any pointers?

The GTKSharp seems more like an expected GTK3 behavior.
Here is the reference manual from developer.gnome.org
Espcially useful should be the Table 1. Selector syntax section.
In short the elements are named after the GTK class name: GtkButton, GtkLabel and so on.
For a class list of default GTK3 wigets check out the docs talbe of content..
The GTK button is a container wiget that doesn't render background so without seeing the actual CSS properties you try to apply using that selector I can't tell you why it doesn't work but so you might need to style it content separately. Eg.
GtkButton GtkLabel {
color: lime;
}
The selector itself GtkButton should be correct.

It was a version issue.
Version 3.22 of GTK# detects the GtkButton selector correctly. I was using GTK 3.14's native libraries. There is one unlisted NuGet package that provides win32 libraries for the 3.22 version. Strangely enough, that version detects the old "button", "window"... instead of the "GtkButton", "GtkWindow"... tags.

Related

C# ChromimunFX: How to create multiTab browsing, and isolate between each tab?

I’m trying to use an embedded browser into my WinForms application. I used CefSharp ChromiumWebBrowser, it work perfectly. However, CEFSharp requires the Visual C++ 2013, or the Visual C++ 2008….I think it is a complicated dependency. I'm creating a portable application without the dependency envirenment.
I have found another library, similar CefSharp, also use Chrominum, called ChromiumFX (visit: https://bitbucket.org/chromiumfx/chromiumfx ). The library uses the .Net Framework 3.5 (Default available in Windows 7) , no need to install Visual C++. And it is suitable for my application.
But I don’t find any way to create multi tabs application with this library. Here is what I tried to do:
private void LifeSpanHandler_OnBeforePopup(object sender, CfxOnBeforePopupEventArgs e)
{
e.SetReturnValue(true);
tabPage2.InvokeOnUiThreadIfRequired(() =>
{
ChromiumWebBrowser b = new ChromiumWebBrowser(e.TargetUrl);
b.Dock = DockStyle.Fill;
tabPage2.Controls.Add(b);
});
}
InvokeOnUiThreadIfRequired is an extension method:
public static void InvokeOnUiThreadIfRequired(this Control control, Action action)
{
if (control.InvokeRequired)
{
control.BeginInvoke(action);
}
else
{
action.Invoke();
}
}
But the application error and the program has crashed.
Another thing, when I created a new instance of ChromiumWebBrowser, I want it isolated with another instance, it means do not use the same cookies, sessions with any instance (private browser). In CefSharp, just create a new RequestContext for new instance:
webbrowser.RequestContext = new RequestContext();
But in ChromiumFX, I dont find any way to do that!
Somebody help me? Thank for you help!

How to add content to windows taskbar

I have been trying to figure out, for some time, how to add content to the taskbar next to the clock. You can see examples of this in NetSpeedMonitor or NetWorx. I am a noob to taskbar but I cannot find anything no matter how hard I look. I am not interested in ThumbButtonInfo or NotifyIcon. Here are a a couple examples of content in the taskbar(incase I'm not saying this right). I would like so be able to do something similar to the first one:
Thank you,
Rymn
There's an example in codeproject showing Extending Explorer with Band Objects using .NET and Windows Forms
Build a Release version of BandObjectLib and register it in the Global
Assembly Cache. The easiest way to do this is to open
BandObjectLib.sln in Visual Studio, set the active configuration to
Release and select 'Rebuild Solution' from the 'Build' menu. The
second project in the solution - RegisterLib - is a C++ utility
project that performs the 'gacutil /if BandObjectLib.dll' command that
puts assembly into GAC.
As you probably already know, Band Objects are COM components. And for
the .NET framework to find an assembly that implements a COM component
it must be either be registered in the GAC or located in the directory
of the client application. There are two possible client applications
for Band Objects - explorer.exe and iexplorer.exe. Explorer is located
in the windows directory and IE somewhere inside 'Program Files'. So
GAC is actually the only one option in this case. Thus .NET assemblies
that implement Band Objects should be registered in GAC and all
libraries they depend on - like BandObjectLib.dll - should also be
there.
Assemblies in the GAC must have strong names and thus key pairs are
required. I have provided the BandObjects.snk file with a key pair but
I encourage you to replace it with your own. See the sn.exe tool for
more details.
Create a new Windows Control Library project and call it SampleBars.
We are going to rely on the base functionality of BandObjectLib so we
have to add a reference to BandObjectLib\Relase\bin\BandObjectLib.dll.
As we are developing a 'Hello World Bar', rename UserControl1.cs and
the UserControl1 class inside it appropriately - into HelloWolrdBar.cs
and HelloWorldBar. Also put the following lines at the beginning of
HelloWorldBar.cs:
using BandObjectLib;
using System.Runtime.InteropServices;
Make HelloWorldBar class inherit BandObject instead of
System.Windows.Forms.UserControl. As I mentioned earlier, Band Objects
are COM components so we should use the Guid attribute. Use
guidgen.exe to generate your unique GUID or you can use the one I have
generated for you:
[Guid("AE07101B-46D4-4a98-AF68-0333EA26E113")]
We also have to sign our assembly with a strong name. You can do this
by putting the following line into AssemblyInfo.cs file:
[assembly: AssemblyKeyFile(#"..\..\..\BandObjects.snk")]
Now its time to decide what kind of Band Object we want to develop.
Lets make it an Explorer Toolbar as well as a Horizontal Explorer Bar
(also known as a Browser Communication Band). All we need to do to
implement this decision is to add custom BandObject attribute to our
HelloWorldBar class:
[Guid("AE07101B-46D4-4a98-AF68-0333EA26E113")]
[BandObject("Hello World Bar",
BandObjectStyle.Horizontal | BandObjectStyle.ExplorerToolbar,
HelpText = "Shows bar that says hello.")]
public class HelloWorldBar : BandObject
{ ...
That's enough to make our control available through 'View->Explorer
Bars' and 'View->Toolbars' explorer menus. It also takes care of menu
item text - "Hello World Bar", and hen the menu item is highlighted
status bar displays "Shows bar that says hello.". Don't you like
declarative programming and custom attributes?
Now it is time to open HelloWorldBar.cs in the Visual Studio Designer
and put some controls on it. Although in my version of HelloWorldBar I
decided to put a single button with 'Say Hello' caption on it you are
free to do something more personalized. I made the size of the button
equal to the size of the control's client area and also set its Anchor
property to the combination of all possible styles - 'Top, Bottom,
Left, Right'. The background color is 'HotTrack' and ForeColor is
'Info'.
The BandObject control has several properties specific to the Band
Objects (and so classes derived from it) - Title , MinSize, MaxSize
and IntegralSize. I set Title for HelloWorldBar to "Hello Bar" and
both MinSize and Size to '150, 24'. Oh, and in button's On Click event
handler I put code that displays a message box. This is what my final
code looks like (and most of it was generated by VS.Net):
using System;
using System.ComponentModel;
using System.Windows.Forms;
using BandObjectLib;
using System.Runtime.InteropServices;
namespace SampleBars
{
[Guid("AE07101B-46D4-4a98-AF68-0333EA26E113")]
[BandObject("Hello World Bar", BandObjectStyle.Horizontal
| BandObjectStyle.ExplorerToolbar, HelpText = "Shows bar that says hello.")]
public class HelloWorldBar : BandObject
{
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
public HelloWorldBar()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}
#region Component Designer generated code
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Anchor = (((System.Windows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right);
this.button1.BackColor = System.Drawing.SystemColors.HotTrack;
this.button1.ForeColor = System.Drawing.SystemColors.Info;
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(150, 24);
this.button1.TabIndex = 0;
this.button1.Text = "Say Hello";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// HelloWorldBar
//
this.Controls.AddRange(new System.Windows.Forms.Control[] { this.button1 });
this.MinSize = new System.Drawing.Size(150, 24);
this.Name = "HelloWorldBar";
this.Size = new System.Drawing.Size(150, 24);
this.Title = "Hello Bar";
this.ResumeLayout(false);
}
#endregion
private void button1_Click(object sender, System.EventArgs e)
{
MessageBox.Show("Hello, World!");
}
}
}
Ok, now we are ready to build SampleBars.dll but its not enough to see
it in explorer yet. We have to put our assembly into the GAC as well
as register it as a COM server. There are tools - gacutil.exe and
regasm.exe that do just this. The C++ utility project named Register
in my version of the SampleBars solution liberates me from using these
tools manually. It has no files in it, just the following post-build
command (debug version):
cd $(ProjectDir)..\bin\Debug
gacutil /if SampleBars.dll
regasm SampleBars.dll
Of cause you have to make sure that Register project is the last one
to be built in the solution using Project Dependencies / Build Order.
After building the solution, and executing the gacutil and regasm
commands, we are finally ready to start Explorer and see our toolbar
and explorer bar. And if you did everything right you should be able
to see something like the picture at the top of the article. On this
picture you can also see how HelloWorldBar looks in the Windows
Taskbar. To achieve this all you need to do is to modify BandObject
attribute adding the BandObjectStyle.TaskbarToolBar flag.
Also you might want to look at this answer
According to Microsoft, Deskbands are not recommended for Windows
7, although they still work. Also keep in mind that Microsoft
requires that Deskbands support Aero on Windows 7 via IDeskband2
Interface, rather than IDeskband. Also, Micorosft has officially said
that IDeskBand2 may be altered or unavailable in subsequent versions
of the operating system or product.
Finally, be very careful about creating shell extensions in managed
code.

Silverlight C# - ComponentOne Spellchecker not loading dictionary

This may be a long shot, but I'm using ComponentOne's Spellchecker control for Silverlight. I made a test project, added a plain textbox and a button to it, added the references to the C1.Silverlight and C1.Silverlight.SpellChecker bits, and added the dictionary file to my project.
In the code, I called up the spellchecker on button1's click event and it worked SPLENDIDLY. The spellchecker dialog shows up, and works exactly as it should.
Since that test was successful, I then tried to implement this into my existing project. I've had no success for absolutely NO reason that I can determine, since I used the EXACT SAME code.
Here's the code I use to call the component:
using C1.Silverlight;
using C1.Silverlight.SpellChecker;
using C1.Silverlight.Resources;
public partial class MainPage : UserControl
{
C1SpellChecker spellChecker = new C1SpellChecker();
public MainPage()
{
InitializeComponent();
spellChecker.MainDictionary.LoadAsync("C1Spell_en-US.dct");
}
private void btnSpelling_Click(object sender, RoutedEventArgs e)
{
var dlg = new C1SpellDialog();
spellChecker.CheckControlAsync(txtArticle, false, dlg);
}
The references to C1.Silverlight and C1.Silverlight.Spellchecker are added to this project as well, and the dictionary as been added in the same fashion as well. The issue seems to be that for whatever reason the dictionary is not loading, because the spellChecker.Enabled method returns whether or not the main dictionary has been loaded. If I call MessageBox.Show("SpellChecker Enabled = " + spellChecker.Enabled.ToString()); it shows false, even though the call to load the dictionary is there (as you can see).
What would cause the dictionary to not load? Have I added it to my project incorrectly somehow?
EDIT: I suspect that I have added the dictionary to the project incorrectly, because the ComponentOne reference states:
If C1SpellChecker cannot find the
spelling dictionary, it will not throw
any exceptions. The Enabled property
will be set to false and the component
will not be able to spell-check any
text.
I just don't know what's wrong though because it was added in the same way that it was in the test project (Right clicked on the project.web->Add->Existing Item)
As always, thank you!
-Sootah
You could add the dictionary to the Silverlight app as an embedded resource and then load it using this code:
public MainPage()
{
InitializeComponent();
// load C1SpellChecker dictionary from embedded resource
var asm = this.GetType().Assembly;
foreach (var res in asm.GetManifestResourceNames())
{
if (res.EndsWith(".dct"))
{
using (var s = asm.GetManifestResourceStream(res))
{
sc.MainDictionary.Load(s);
break;
}
}
}
}
I think this post is duplicated in our forum as well, but will answer first here. Please try this:
1) Try to access the .dct file using your browser. If you cannot see it, it's probably because your web server is not serving that type of files. You need ton configure the web server to allow it.
2) verify the URL you are using is correct.http://helpcentral.componentone.com/CS/silverlight_161/f/78/p/86955/241328.aspx#241328
3) Check you are setting everything correctly: http://helpcentral.componentone.com/CS/silverlight_161/f/78/p/81924/227790.aspx#227790
Hope this helps!

Why do 'requires' statements fail when loading (iron)ruby script via a C# program?

IronRuby and VS2010 noob question:
I'm trying to do a spike to test the feasibility of interop between a C# project and an existing RubyGem rather than re-invent that particular wheel in .net. I've downloaded and installed IronRuby and the RubyGems package, as well as the gem I'd ultimately like to use.
Running .rb files or working in the iirb Ruby console is without problems. I can load the both the RubyGems package, and the gem itself and use it, so, at least for that use case, my environment is set up correctly.
However, when I try to do the same sort of thing from within a C# (4.0) console app, it complains about the very first line:
require 'RubyGems'
With the error:
no such file to load -- rubygems
My Console app looks like this:
using System;
using IronRuby;
namespace RubyInteropSpike
{
class Program
{
static void Main(string[] args)
{
var runtime = Ruby.CreateRuntime();
var scope = runtime.ExecuteFile("test.rb");
Console.ReadKey();
}
}
}
Removing the dependencies and just doing some basic self-contained Ruby stuff works fine, but including any kind of 'requires' statement seems to cause it to fail.
I'm hoping that I just need to pass some additional information (paths, etc) to the ruby runtime when I create it, and really hoping that this isn't some kind of limitation, because that would make me sad.
Short answer: Yes, this will work how you want it to.You need to use the engine's SetSearchPaths method to do what you wish.
A more complete example
(Assumes you loaded your IronRuby to C:\IronRubyRC2 as the root install dir)
var engine = IronRuby.Ruby.CreateEngine();
engine.SetSearchPaths(new[] {
#"C:\IronRubyRC2\Lib\ironruby",
#"C:\IronRubyRC2\Lib\ruby\1.8",
#"C:\IronRubyRC2\Lib\ruby\site_ruby\1.8"
});
engine.Execute("require 'rubygems'"); // without SetSearchPaths, you get a LoadError
/*
engine.Execute("require 'restclient'"); // install through igem, then check with igem list
engine.Execute("puts RestClient.get('http://localhost/').body");
*/
Console.ReadKey();

How to make designer generated .Net application settings portable

I've been looking at modifying the source of the Doppler podcast aggregator with the goal of being able to run the program directly from my mp3 player.
Doppler stores application settings using a Visual Studio designer generated Settings class, which by default serializes user settings to the user's home directory. I'd like to change this so that all settings would be stored in the same directory as the exe.
It seems that this would be possible by creating a custom provider class which inherits the SettingsProvider class. Has anyone created such a provider and would like to share code?
Update: I was able to get a custom settings provider nearly working by using this MSDN sample, i.e. with simple inheritance. I was initially confused as Windows Forms designer stopped working until I did this trick suggested at Codeproject:
internal sealed partial class Settings
{
private MySettingsProvider settingsprovider = new MySettingsProvider();
public Settings()
{
foreach (SettingsProperty property in this.Properties)
{
property.Provider = settingsprovider;
}
...
The program still starts with window size 0;0 though.
Anyone with any insight to this?
Why the need to assing the provider in runtime---instead of using attributes as suggested by MSDN?
Why the changes in how the default settings are passed to the application with the default settings provider vs. the custom one?
Why not use the CodeProject PortableSettingsProvider solution as is (with a few minor changes) ?
I have done so in my project (StreamRecorder.NET) with success.
Some comments on the project's page were useful:
http://www.codeproject.com/Messages/2934144/Fixed-csharp-version.aspx
http://www.codeproject.com/Messages/3285411/Re-Win-Form-Designer-breaking-with-custom-Settings.aspx
And the code I ended up with:
static void Main(string[] args)
{
if (args.Contains("-p") || args.Contains("--portable"))
{
MakePortable(Properties.Settings.Default);
MakePortable(Properties.LastUsedSettings.Default);
MakePortable(Properties.DefaultSettings.Default);
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm(args));
}
private static void MakePortable(ApplicationSettingsBase settings)
{
var portableSettingsProvider =
new PortableSettingsProvider(settings.GetType().Name + ".settings");
settings.Providers.Add(portableSettingsProvider);
foreach (System.Configuration.SettingsProperty prop in settings.Properties)
prop.Provider = portableSettingsProvider;
settings.Reload();
}
Lastly I made these changes to the CP project:
string _fileName;
public PortableSettingsProvider(string fileName)
{
_fileName = fileName;
}
public virtual string GetAppSettingsFilename()
{
//Used to determine the filename to store the settings
//return ApplicationName + ".settings";
return _fileName;
}
I know this question is quite old already. I just want to share my own version of a portable settings provider which I published as nuget package here.
The usage is pretty simple:
// make the default settings class portable
PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
I also explained the basic strategy of this implementation at https://www.codeproject.com/Articles/1238550/Making-Application-Settings-Portable.
Just to 'close' the question: The somewhat unsatisfactory solution I ended up with was
Create a custom settings provider, which inherits from SettingsProvider and stores the settings in a XML file
Set the Provider property of each of the setting (by selecting the entire grid in the designer) to the custom settings provider using the designer
Drawbacks: The forms designer breaks and gives an exception which basically says that the custom provider class cannot be found. The built exe however works OK. Setting the provider in the code as described in the question makes the designer work, but then for some reason, which I haven't looked closely at, the settings won't serialize.
It seems that making settings portable was all that was needed to make Doppler portable. Whether I'll start using Doppler as my main podcast aggregator or stick with my homebrew command line aggregator, I'll see.

Categories