This is a page describing my programming project, called Artem. Artem is a tool which provides you functionality of making web photo albums.
Used resources:
Download: Artem (needs the MS Visual Studio installed)
Albums made with Artem:
→ Florida
→ Winter Holidays
→ Autumn 2007
→ Winter 2007–2008
Ok. I wanna add ability to save&load photo album projects. It is going to have the following data:
However there is another problem. My scheme of plugin and picture list interaction is built in a way that they are independent. They are even in different assemblies. So, if I want to save project properties I have to use its properties. And simultaneously I need to store pictures' properties. So, where to place the functionality: inside the plugin, or inside the GUI application?
Considering the second variant I can simply save all the options (both plugin's properties and picture comments). But how can I make my plugin able to allow me loading that project file?
I heard something about actions, not properties in C#. I might put those two actions to the plugin and use 'em from property viewer.
Here is the question:
property
of the picture
class, and when we select an image it starts to generate the thumbnail and then shows right in the property grid field. Difficulty of this approach is that I should invent a way how to display this field. Another difficulty is that if make it like an implicit property
it will be executed each time I call it or GUI call it. But the execution does take time. So, it's gonna be retarded if made implicitly.
Another way is to leave some place on the form just for the preview image. It is much easier, because nothing to invent — just insert and use it. The question is: where the fuck to place?
Have designed it like that: put all three controls into TableLayout
:
CheckBox
called previewableCheckBox with absolute size
;PictureBox
called previewPictureBox with auto size
;PropertyGrid
called propertyViewer with percent size
equal to 100%.----------- | Property | | grid | | | | | | | | | | | ----------- | | | | | | V V _________________________ | V ___________ ___________ |v CheckBox | |o CheckBox | ------------- ------------- | Picture | | Property | | preview | => | grid | ------------- | | | Property | | | | grid | | | ----------- -----------
Scaling colors ms-help://MS.MSDNQTR.2005JAN.1033/cpguide/html/_gdiplus_Scaling_Colors_usecsharp.htm
What I did finally is just added all R, G and B components together and divided them by 3.
Thanks to Sergey Babin and rsdn article I've finally performed that dream about properties separations by categories (using System.ComponentModel.CategoryAttribute). Also I've applied DisplayName and Description attributes for the displaying name of a property and for detailed description at the bottom of the grid accordingly.
Having a lot of functional plugins that are to be loaded to your application and — properties of those plugins that are to be shown in a PropertyGrid by calling PropertyGrid.SelectedObject it becomes looking like a big heap of trash. Especially if some plugins contain another ones or — inherit 'em.
One way to improve the situation is to set a number of attribute classes to the PropertyGrid.BrowsableAttributes that are to be displayed by the grid if the object owns those attributes.
Now the resize plugin works very simple. It declares a hidden field that represents the value of the biggest image side size which is threshold: if requiring side size is bigger than the threshold value we call first procedure to resize the picture and if less — procedure number 2. But what is the most interesting is that no actually work about resizing made by myself (no code written).
The first procedure uses Image.GetThumbnail() method. The second one just creates new Bitmap using constructor providing new sides sizes for the Bitmap.
So, it's not a surprise why the quality is so poor. Well, it's actually even more poor if only one of the former procedures used for both size ranges, but at the same time I wanna get nice pictures.
The offer is to use GDI+ Graphics class, that can be constructed from a Image instance. Then I resize the Graphics and unload it to some file.
Then, why this method is gonna bring me nice pictures, is because the Graphics provides some custom parameters:
You see I can set interpolation and smoothing modes that really does improve the quality. The second note is that two smoothing modes antialias and highquality seem to be the same.
Want to design a class that generates html file.
It works like that:
HTMLGenerator g = new HTMLGenerator( "./index.html" ); g.Head.Title.value = "This is a title for this file"; g.Head.Style.src = "./css/mystyle.css"; g.Head.Style.add( "#container{ margin: 0; padding: 0; width: 100%; height: 100%; border: none; }" ); g.Head.Generate(); g.Body.Style.backgroundColor = "gray"; g.Body.Style.border = "none"; g.Body.rawAdd( "<div id="container"><h1>Hi, people</h1></div>" ); g.Body.Generate(); g.Finish();
I'm gonna write a separate class manipulating on images that are used in Artem. So it's goona be no need to inherit a lot of classes inside another ones just to have the same ability to manipulate on pictures.
I want that class to be able returning
But that shit seems to be too complicated at least for the most typical user that isn't so a nerd html-writer as I am %).
So, at first I'm going to implement some predefined set of html-styles. Somewhat like enumerable property of the plugin class.
It works but works not as well as I want it to: (1) low quality result pictures and (2) very slow on big files.
First problem, probably could be solved by use of DirectX library.
Second problem could be solved by applying technique called lazy allocation: allocate memory exactly at the moment when the object is gonna be used. And moreover, after usage I can free the memory manually so as not to eat so much brains of my poor laptop :).
Gosh, it feels much better when you stop programming every 40 minutes and just make some physical exercises and look out the window (do you have one at your workplace or cubicle? ).
Ok. We have plugins to be added dynamically. And we gonna add some GUI control, that provides us ability to add clickable controls, delegating execution to the plugin that is just added. I.e. we claim that the plugin should own an EventHandler method.
But, if I delegate execution to IFunction.handler() and at the same time it doesn't know anything about picture it's supposed to work on. But we can first call method of this plugin that sets the picture on what it's gonna work.
It works, but I had to add direct reference to the plugin library, because I had to cast object to Function.IFunctionPlugin when I was constructing a delegate:
foreach( Type t in pluginTypes ) { object o = Activator.CreateInstance(t); // Object o should own a handler suitable for // EventHandler delegate, so we put that // handler inside MenuItem constructor MethodInfo Shortname = (t.GetProperty("Shortname")).GetGetMethod(); MethodInfo handler = t.GetMethod("handler"); mi.MenuItems.Add( new MenuItem( (string) Shortname.Invoke(o, null), new EventHandler(((FunctionPlugin.IFunctionPlugin)o).handler) ) ); }
So use of button isn't suitable: when you click the button - you expect that it's gonna work out, show some function, but instead of that you get the properties of the plugin. Seems stupid for me.
System.Windows.Forms.ListBox seems a good solution. To put an item into the listbox the item is supposed supporting System.ComponentModel.IComponent. So we derive our plugins from System.Windows.Forms.Control (which implements IComponent) and then we can just put instances of our plugins directly to the listbox.
Tried to generate ToolStrip by the studio, then paying a lot of attention looked what it generated and now I'm gonna try to repeat that by myself having written class ToolBarGenerator. private void InitializeComponent() performs the following:
Yep, CheckedListBox seems very very convenient.
public virtual object perform(object o);This functions accepts array of pictures which are selected in the checkedListBox field of the GUI, whether it's gonna be used or not by the plugin. And then the perform() method returns array of pictures which should be added to that checkedListBox.
Thus, if any plugin gets null as a selected pictures inside the listbox, but following by the business logic of the plugin this list of pictures should not be empty, it just retunrs null, meaning that it has got nothing to do. And then the program just does nothing. User should check some pictures before call this method. That's it. Very simple.
Ivan Yurlagin,